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 -------------------------- */
167 XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
168 struct xgi_hw_device_info *HwDeviceExtension,
169 unsigned char modeno, unsigned char rateindex)
171 unsigned short ModeNo = modeno;
172 unsigned short ModeIdIndex = 0, ClockIndex = 0;
173 unsigned short RefreshRateTableIndex = 0;
175 /*unsigned long temp = 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(struct vb_device_info *XGI_Pr,
204 struct xgi_hw_device_info *HwDeviceExtension,
205 unsigned char modeno, unsigned char rateindex,
206 u32 *left_margin, u32 *right_margin,
207 u32 *upper_margin, u32 *lower_margin,
208 u32 *hsync_len, u32 *vsync_len,
209 u32 *sync, u32 *vmode)
211 unsigned short ModeNo = modeno;
212 unsigned short ModeIdIndex = 0, index = 0;
213 unsigned short RefreshRateTableIndex = 0;
215 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
216 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
217 unsigned char sr_data, cr_data, cr_data2;
218 unsigned long cr_data3;
219 int A, B, C, D, E, F, temp, j;
220 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
221 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
222 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
224 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
227 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
228 RefreshRateTableIndex += (rateindex - 1);
230 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
232 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
234 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
236 /* Horizontal total */
237 HT = (cr_data & 0xff) |
238 ((unsigned short) (sr_data & 0x03) << 8);
241 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
243 Horizontal display enable end
244 HDE = (cr_data & 0xff) |
245 ((unsigned short) (sr_data & 0x0C) << 6);*/
246 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
249 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
251 /* Horizontal retrace (=sync) start */
252 HRS = (cr_data & 0xff) |
253 ((unsigned short) (sr_data & 0xC0) << 2);
256 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
258 /* Horizontal blank start */
259 HBS = (cr_data & 0xff) |
260 ((unsigned short) (sr_data & 0x30) << 4);
262 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
264 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
266 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
268 /* Horizontal blank end */
269 HBE = (cr_data & 0x1f) |
270 ((unsigned short) (cr_data2 & 0x80) >> 2) |
271 ((unsigned short) (sr_data & 0x03) << 6);
273 /* Horizontal retrace (=sync) end */
274 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
276 temp = HBE - ((E - 1) & 255);
277 B = (temp > 0) ? temp : (temp + 256);
279 temp = HRE - ((E + F + 3) & 63);
280 C = (temp > 0) ? temp : (temp + 64);
284 *left_margin = D * 8;
285 *right_margin = F * 8;
288 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
290 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
292 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
295 VT = (cr_data & 0xFF) |
296 ((unsigned short) (cr_data2 & 0x01) << 8) |
297 ((unsigned short)(cr_data2 & 0x20) << 4) |
298 ((unsigned short) (sr_data & 0x01) << 10);
301 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
303 /* Vertical display enable end */
304 /* VDE = (cr_data & 0xff) |
305 ((unsigned short) (cr_data2 & 0x02) << 7) |
306 ((unsigned short) (cr_data2 & 0x40) << 3) |
307 ((unsigned short) (sr_data & 0x02) << 9); */
308 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1;
311 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
313 /* Vertical retrace (=sync) start */
314 VRS = (cr_data & 0xff) |
315 ((unsigned short) (cr_data2 & 0x04) << 6) |
316 ((unsigned short) (cr_data2 & 0x80) << 2) |
317 ((unsigned short) (sr_data & 0x08) << 7);
320 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
322 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
324 /* Vertical blank start */
325 VBS = (cr_data & 0xff) |
326 ((unsigned short) (cr_data2 & 0x08) << 5) |
327 ((unsigned short) (cr_data3 & 0x20) << 4) |
328 ((unsigned short) (sr_data & 0x04) << 8);
330 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
332 /* Vertical blank end */
333 VBE = (cr_data & 0xff) |
334 ((unsigned short) (sr_data & 0x10) << 4);
335 temp = VBE - ((E - 1) & 511);
336 B = (temp > 0) ? temp : (temp + 512);
338 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
340 /* Vertical retrace (=sync) end */
341 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
342 temp = VRE - ((E + F - 1) & 31);
343 C = (temp > 0) ? temp : (temp + 32);
351 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
352 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
354 *sync |= FB_SYNC_VERT_HIGH_ACT;
356 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
357 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
359 *sync |= FB_SYNC_HOR_HIGH_ACT;
361 *vmode = FB_VMODE_NONINTERLACED;
362 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
363 *vmode = FB_VMODE_INTERLACED;
366 while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
367 if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
368 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
369 if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
370 *vmode = FB_VMODE_DOUBLE;
384 static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
386 XGI_Pr->RelIO = BaseAddr;
387 XGI_Pr->P3c4 = BaseAddr + 0x14;
388 XGI_Pr->P3d4 = BaseAddr + 0x24;
389 XGI_Pr->P3c0 = BaseAddr + 0x10;
390 XGI_Pr->P3ce = BaseAddr + 0x1e;
391 XGI_Pr->P3c2 = BaseAddr + 0x12;
392 XGI_Pr->P3ca = BaseAddr + 0x1a;
393 XGI_Pr->P3c6 = BaseAddr + 0x16;
394 XGI_Pr->P3c7 = BaseAddr + 0x17;
395 XGI_Pr->P3c8 = BaseAddr + 0x18;
396 XGI_Pr->P3c9 = BaseAddr + 0x19;
397 XGI_Pr->P3da = BaseAddr + 0x2A;
398 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
399 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
400 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
401 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
402 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
407 void XGIfb_set_reg4(u16 port, unsigned long data)
409 outl((u32) (data & 0xffffffff), port);
412 u32 XGIfb_get_reg3(u16 port)
420 /* ------------ Interface for init & mode switching code ------------- */
423 XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext,
424 unsigned long offset, unsigned long set, unsigned long *value)
426 static struct pci_dev *pdev = NULL;
427 static unsigned char init = 0, valid_pdev = 0;
430 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
432 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
436 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
444 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
445 xgi_video_info.chip_id);
450 pci_read_config_dword(pdev, offset, (u32 *)value);
452 pci_write_config_dword(pdev, offset, (u32)(*value));
457 /*unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
458 unsigned long offset, unsigned long set, unsigned long *value)
460 static struct pci_dev *pdev = NULL;
461 static unsigned char init = 0, valid_pdev = 0;
466 switch (xgi_video_info.chip) {
468 nbridge_id = PCI_DEVICE_ID_XG_540;
471 nbridge_id = PCI_DEVICE_ID_XG_630;
474 nbridge_id = PCI_DEVICE_ID_XG_730;
477 nbridge_id = PCI_DEVICE_ID_XG_550;
480 nbridge_id = PCI_DEVICE_ID_XG_650;
483 nbridge_id = PCI_DEVICE_ID_XG_740;
490 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
496 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
502 pci_read_config_dword(pdev, offset, (u32 *)value);
504 pci_write_config_dword(pdev, offset, (u32)(*value));
509 /* ------------------ Internal helper routines ----------------- */
511 static void XGIfb_search_mode(const char *name)
516 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
517 xgifb_mode_idx = DEFAULT_MODE;
518 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
520 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
526 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
527 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
528 xgifb_mode_idx = DEFAULT_MODE;
529 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
531 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
536 while(XGIbios_mode[i].mode_no != 0) {
537 l = min(strlen(name), strlen(XGIbios_mode[i].name));
538 if (!strncmp(name, XGIbios_mode[i].name, l)) {
545 if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
548 static void XGIfb_search_vesamode(unsigned int vesamode)
554 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
555 xgifb_mode_idx = DEFAULT_MODE;
556 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
558 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
563 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
565 while(XGIbios_mode[i].mode_no != 0) {
566 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
567 (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
574 if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
577 static int XGIfb_GetXG21LVDSData(void)
580 unsigned char *pData;
583 inXGIIDXREG(XGISR,0x1e,tmp);
584 outXGIIDXREG(XGISR, 0x1e, tmp|4);
586 pData = xgi_video_info.mmio_vbase+0x20000;
587 if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
589 i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
598 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
599 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
600 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
601 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
602 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
603 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
604 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
605 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
606 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
607 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
608 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
609 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
610 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
611 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
612 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
613 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
618 (k < (sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct))));
624 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
628 int XGIfb_mode_idx = 0;
631 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
632 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
634 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
635 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
636 (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
638 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
647 return (XGIfb_mode_idx);
651 static int XGIfb_validate_mode(int myindex)
655 if (xgi_video_info.chip == XG21)
657 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
659 xres = XGI21_LCDCapList[0].LVDSHDE;
660 yres = XGI21_LCDCapList[0].LVDSVDE;
661 if(XGIbios_mode[myindex].xres > xres)
663 if(XGIbios_mode[myindex].yres > yres)
665 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
667 if (XGIbios_mode[myindex].bpp > 8)
676 /* FIXME: for now, all is valid on XG27 */
677 if (xgi_video_info.chip == XG27)
680 if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
683 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
685 switch (XGIhw_ext.ulCRT2LCDType) {
687 xres = 640; yres = 480; break;
689 xres = 800; yres = 600; break;
691 xres = 1024; yres = 600; break;
693 xres = 1024; yres = 768; break;
695 xres = 1152; yres = 768; break;
697 xres = 1280; yres = 960; break;
699 xres = 1280; yres = 768; break;
701 xres = 1280; yres = 1024; break;
703 xres = 1400; yres = 1050; break;
705 xres = 1600; yres = 1200; break;
706 // case LCD_320x480: // TW: FSTN
707 // xres = 320; yres = 480; break;
709 xres = 0; yres = 0; break;
711 if(XGIbios_mode[myindex].xres > xres) {
714 if(XGIbios_mode[myindex].yres > yres) {
717 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
718 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
720 switch (XGIbios_mode[myindex].xres) {
722 if(XGIbios_mode[myindex].yres != 512) return -1;
723 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
726 if((XGIbios_mode[myindex].yres != 400) &&
727 (XGIbios_mode[myindex].yres != 480))
731 if(XGIbios_mode[myindex].yres != 600) return -1;
734 if((XGIbios_mode[myindex].yres != 600) &&
735 (XGIbios_mode[myindex].yres != 768))
737 if((XGIbios_mode[myindex].yres == 600) &&
738 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
742 if((XGIbios_mode[myindex].yres) != 768) return -1;
743 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
746 if((XGIbios_mode[myindex].yres != 768) &&
747 (XGIbios_mode[myindex].yres != 1024))
749 if((XGIbios_mode[myindex].yres == 768) &&
750 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
754 if(XGIbios_mode[myindex].yres != 1050) return -1;
757 if(XGIbios_mode[myindex].yres != 1200) return -1;
763 switch (XGIbios_mode[myindex].xres) {
765 if(XGIbios_mode[myindex].yres != 512) return -1;
768 if((XGIbios_mode[myindex].yres != 400) &&
769 (XGIbios_mode[myindex].yres != 480))
773 if(XGIbios_mode[myindex].yres != 600) return -1;
776 if(XGIbios_mode[myindex].yres != 768) return -1;
779 if((XGIbios_mode[myindex].yres != 960) &&
780 (XGIbios_mode[myindex].yres != 1024))
782 if(XGIbios_mode[myindex].yres == 960) {
783 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
788 if(XGIbios_mode[myindex].yres != 1050) return -1;
791 if(XGIbios_mode[myindex].yres != 1200) return -1;
799 switch (XGIbios_mode[myindex].xres) {
805 if (xgi_video_info.TV_type == TVMODE_NTSC) {
806 if (XGIbios_mode[myindex].yres != 480) {
809 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
810 if (XGIbios_mode[myindex].yres != 576) {
814 // TW: LVDS/CHRONTEL does not support 720
815 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
816 xgi_video_info.hasVB == HASVB_CHRONTEL) {
821 if (xgi_video_info.TV_type == TVMODE_NTSC) {
822 if(XGIbios_mode[myindex].bpp == 32) {
826 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
827 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
828 xgi_video_info.hasVB == HASVB_CHRONTEL) {
829 if(xgi_video_info.chip < XGI_315H) {
839 if(XGIbios_mode[myindex].xres > 1280) return -1;
846 static void XGIfb_search_crt2type(const char *name)
853 while(XGI_crt2type[i].type_no != -1) {
854 if (!strcmp(name, XGI_crt2type[i].name)) {
855 XGIfb_crt2type = XGI_crt2type[i].type_no;
856 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
861 if(XGIfb_crt2type < 0)
862 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
865 static void XGIfb_search_queuemode(const char *name)
872 while (XGI_queuemode[i].type_no != -1) {
873 if (!strcmp(name, XGI_queuemode[i].name)) {
874 XGIfb_queuemode = XGI_queuemode[i].type_no;
879 if (XGIfb_queuemode < 0)
880 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
883 static u8 XGIfb_search_refresh_rate(unsigned int rate)
888 xres = XGIbios_mode[xgifb_mode_idx].xres;
889 yres = XGIbios_mode[xgifb_mode_idx].yres;
892 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
893 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
894 if (XGIfb_vrate[i].refresh == rate) {
895 XGIfb_rate_idx = XGIfb_vrate[i].idx;
897 } else if (XGIfb_vrate[i].refresh > rate) {
898 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
899 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
900 rate, XGIfb_vrate[i].refresh);
901 XGIfb_rate_idx = XGIfb_vrate[i].idx;
902 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
903 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
904 && (XGIfb_vrate[i].idx != 1)) {
905 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
906 rate, XGIfb_vrate[i-1].refresh);
907 XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
908 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
911 } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
912 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
913 rate, XGIfb_vrate[i].refresh);
914 XGIfb_rate_idx = XGIfb_vrate[i].idx;
920 if (XGIfb_rate_idx > 0) {
921 return XGIfb_rate_idx;
924 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
929 static void XGIfb_search_tvstd(const char *name)
936 while (XGI_tvtype[i].type_no != -1) {
937 if (!strcmp(name, XGI_tvtype[i].name)) {
938 XGIfb_tvmode = XGI_tvtype[i].type_no;
945 static unsigned char XGIfb_bridgeisslave(void)
947 unsigned char usScratchP1_00;
949 if (xgi_video_info.hasVB == HASVB_NONE)
952 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
953 if ((usScratchP1_00 & 0x50) == 0x10)
959 static unsigned char XGIfbcheckvretracecrt1(void)
963 inXGIIDXREG(XGICR,0x17,temp);
968 inXGIIDXREG(XGISR,0x1f,temp);
972 if (inXGIREG(XGIINPSTAT) & 0x08)
978 static unsigned char XGIfbcheckvretracecrt2(void)
981 if (xgi_video_info.hasVB == HASVB_NONE)
983 inXGIIDXREG(XGIPART1, 0x30, temp);
990 static unsigned char XGIfb_CheckVBRetrace(void)
992 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
993 if(XGIfb_bridgeisslave()) {
994 return(XGIfbcheckvretracecrt1());
996 return(XGIfbcheckvretracecrt2());
999 return(XGIfbcheckvretracecrt1());
1002 /* ----------- FBDev related routines for all series ----------- */
1005 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1007 switch(var->bits_per_pixel) {
1009 var->red.offset = var->green.offset = var->blue.offset = 0;
1010 var->red.length = var->green.length = var->blue.length = 6;
1011 xgi_video_info.video_cmap_len = 256;
1014 var->red.offset = 11;
1015 var->red.length = 5;
1016 var->green.offset = 5;
1017 var->green.length = 6;
1018 var->blue.offset = 0;
1019 var->blue.length = 5;
1020 var->transp.offset = 0;
1021 var->transp.length = 0;
1022 xgi_video_info.video_cmap_len = 16;
1025 var->red.offset = 16;
1026 var->red.length = 8;
1027 var->green.offset = 8;
1028 var->green.length = 8;
1029 var->blue.offset = 0;
1030 var->blue.length = 8;
1031 var->transp.offset = 24;
1032 var->transp.length = 8;
1033 xgi_video_info.video_cmap_len = 16;
1040 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1041 struct fb_info *info)
1044 unsigned int htotal = var->left_margin + var->xres +
1045 var->right_margin + var->hsync_len;
1046 unsigned int vtotal = var->upper_margin + var->yres +
1047 var->lower_margin + var->vsync_len;
1048 #if defined(__powerpc__)
1049 u8 sr_data, cr_data;
1051 unsigned int drate = 0, hrate = 0;
1054 // unsigned char reg,reg1;
1056 DEBUGPRN("Inside do_set_var");
1057 // 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);
1059 info->var.xres_virtual = var->xres_virtual;
1060 info->var.yres_virtual = var->yres_virtual;
1061 info->var.bits_per_pixel = var->bits_per_pixel;
1063 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1065 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1067 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1073 if(!htotal || !vtotal) {
1074 DPRINTK("XGIfb: Invalid 'var' information\n");
1077 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1078 var->pixclock,htotal,vtotal);
1082 if(var->pixclock && htotal && vtotal) {
1083 drate = 1000000000 / var->pixclock;
1084 hrate = (drate * 1000) / htotal;
1085 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1087 xgi_video_info.refresh_rate = 60;
1090 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1091 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1093 old_mode = xgifb_mode_idx;
1096 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1097 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1098 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1099 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1100 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1101 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1109 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1111 xgifb_mode_idx = -1;
1113 if(xgifb_mode_idx < 0) {
1114 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1115 var->yres, var->bits_per_pixel);
1116 xgifb_mode_idx = old_mode;
1120 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1121 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1122 xgi_video_info.refresh_rate = 60;
1128 XGIfb_pre_setmode();
1129 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1130 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1133 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1135 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1137 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1138 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1140 XGIfb_post_setmode();
1142 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1143 XGIbios_mode[xgifb_mode_idx].xres,
1144 XGIbios_mode[xgifb_mode_idx].yres,
1145 XGIbios_mode[xgifb_mode_idx].bpp,
1146 xgi_video_info.refresh_rate);
1148 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1149 xgi_video_info.video_vwidth = info->var.xres_virtual;
1150 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1151 xgi_video_info.video_vheight = info->var.yres_virtual;
1152 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1153 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1154 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1155 xgi_video_info.accel = 0;
1157 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1159 switch(xgi_video_info.video_bpp)
1162 xgi_video_info.DstColor = 0x0000;
1163 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1164 xgi_video_info.video_cmap_len = 256;
1165 #if defined(__powerpc__)
1166 inXGIIDXREG (XGICR, 0x4D, cr_data);
1167 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1171 xgi_video_info.DstColor = 0x8000;
1172 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1173 #if defined(__powerpc__)
1174 inXGIIDXREG (XGICR, 0x4D, cr_data);
1175 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1177 xgi_video_info.video_cmap_len = 16;
1180 xgi_video_info.DstColor = 0xC000;
1181 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1182 xgi_video_info.video_cmap_len = 16;
1183 #if defined(__powerpc__)
1184 inXGIIDXREG (XGICR, 0x4D, cr_data);
1185 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1189 xgi_video_info.video_cmap_len = 16;
1190 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1191 xgi_video_info.accel = 0;
1195 XGIfb_bpp_to_var(var); /*update ARGB info*/
1196 DEBUGPRN("End of do_set_var");
1203 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1207 // printk("Inside pan_var");
1209 if (var->xoffset > (var->xres_virtual - var->xres)) {
1210 // printk( "Pan: xo: %d xv %d xr %d\n",
1211 // var->xoffset, var->xres_virtual, var->xres);
1214 if(var->yoffset > (var->yres_virtual - var->yres)) {
1215 // printk( "Pan: yo: %d yv %d yr %d\n",
1216 // var->yoffset, var->yres_virtual, var->yres);
1219 base = var->yoffset * var->xres_virtual + var->xoffset;
1221 /* calculate base bpp dep. */
1222 switch(var->bits_per_pixel) {
1234 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1236 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1237 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1238 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1239 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1240 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1242 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1243 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1244 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1245 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1246 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1247 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1249 // printk("End of pan_var");
1255 void XGI_dispinfo(struct ap_data *rec)
1257 rec->minfo.bpp = xgi_video_info.video_bpp;
1258 rec->minfo.xres = xgi_video_info.video_width;
1259 rec->minfo.yres = xgi_video_info.video_height;
1260 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1261 rec->minfo.v_yres = xgi_video_info.video_vheight;
1262 rec->minfo.org_x = xgi_video_info.org_x;
1263 rec->minfo.org_y = xgi_video_info.org_y;
1264 rec->minfo.vrate = xgi_video_info.refresh_rate;
1265 rec->iobase = xgi_video_info.vga_base - 0x30;
1266 rec->mem_size = xgi_video_info.video_size;
1267 rec->disp_state = xgi_video_info.disp_state;
1268 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1269 rec->hasVB = xgi_video_info.hasVB;
1270 rec->TV_type = xgi_video_info.TV_type;
1271 rec->TV_plug = xgi_video_info.TV_plug;
1272 rec->chip = xgi_video_info.chip;
1278 static int XGIfb_open(struct fb_info *info, int user)
1283 static int XGIfb_release(struct fb_info *info, int user)
1288 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1292 switch(var->bits_per_pixel) {
1306 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1307 unsigned transp, struct fb_info *info)
1309 if (regno >= XGIfb_get_cmap_len(&info->var))
1312 switch (info->var.bits_per_pixel) {
1314 outXGIREG(XGIDACA, regno);
1315 outXGIREG(XGIDACD, (red >> 10));
1316 outXGIREG(XGIDACD, (green >> 10));
1317 outXGIREG(XGIDACD, (blue >> 10));
1318 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1319 outXGIREG(XGIDAC2A, regno);
1320 outXGIREG(XGIDAC2D, (red >> 8));
1321 outXGIREG(XGIDAC2D, (green >> 8));
1322 outXGIREG(XGIDAC2D, (blue >> 8));
1326 ((u32 *)(info->pseudo_palette))[regno] =
1327 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1333 ((u32 *) (info->pseudo_palette))[regno] =
1334 (red << 16) | (green << 8) | (blue);
1340 static int XGIfb_set_par(struct fb_info *info)
1344 // printk("XGIfb: inside set_par\n");
1345 if((err = XGIfb_do_set_var(&info->var, 1, info)))
1347 XGIfb_get_fix(&info->fix, -1, info);
1348 // printk("XGIfb:end of set_par\n");
1352 static int XGIfb_check_var(struct fb_var_screeninfo *var,
1353 struct fb_info *info)
1355 unsigned int htotal =
1356 var->left_margin + var->xres + var->right_margin +
1358 unsigned int vtotal = 0;
1359 unsigned int drate = 0, hrate = 0;
1361 int refresh_rate, search_idx;
1363 DEBUGPRN("Inside check_var");
1365 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1366 vtotal = var->upper_margin + var->yres + var->lower_margin +
1369 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1370 vtotal = var->upper_margin + var->yres + var->lower_margin +
1373 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1374 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1376 } else vtotal = var->upper_margin + var->yres + var->lower_margin +
1379 if(!(htotal) || !(vtotal)) {
1380 XGIFAIL("XGIfb: no valid timing data");
1384 if(var->pixclock && htotal && vtotal) {
1385 drate = 1000000000 / var->pixclock;
1386 hrate = (drate * 1000) / htotal;
1387 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1389 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1390 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1391 __func__,var->pixclock, htotal, vtotal,
1392 __func__, drate, hrate, xgi_video_info.refresh_rate);
1394 xgi_video_info.refresh_rate = 60;
1398 if((var->pixclock) && (htotal)) {
1399 drate = 1E12 / var->pixclock;
1400 hrate = drate / htotal;
1401 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1402 } else refresh_rate = 60;
1404 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1405 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1408 while((XGIbios_mode[search_idx].mode_no != 0) &&
1409 (XGIbios_mode[search_idx].xres <= var->xres) ) {
1410 if((XGIbios_mode[search_idx].xres == var->xres) &&
1411 (XGIbios_mode[search_idx].yres == var->yres) &&
1412 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1413 if(XGIfb_validate_mode(search_idx) > 0) {
1423 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1424 var->xres, var->yres, var->bits_per_pixel);
1427 while(XGIbios_mode[search_idx].mode_no != 0) {
1429 if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1430 (var->yres <= XGIbios_mode[search_idx].yres) &&
1431 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1432 if(XGIfb_validate_mode(search_idx) > 0) {
1440 var->xres = XGIbios_mode[search_idx].xres;
1441 var->yres = XGIbios_mode[search_idx].yres;
1442 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1443 var->xres, var->yres, var->bits_per_pixel);
1446 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1447 var->xres, var->yres, var->bits_per_pixel);
1452 /* TW: TODO: Check the refresh rate */
1454 /* Adapt RGB settings */
1455 XGIfb_bpp_to_var(var);
1457 /* Sanity check for offsets */
1458 if (var->xoffset < 0)
1460 if (var->yoffset < 0)
1465 if(var->xres != var->xres_virtual)
1466 var->xres_virtual = var->xres;
1467 if(var->yres != var->yres_virtual)
1468 var->yres_virtual = var->yres;
1470 // TW: Now patch yres_virtual if we use panning
1472 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1473 if(var->yres_virtual <= var->yres) {
1474 // TW: Paranoia check
1475 var->yres_virtual = var->yres;
1479 /* Truncate offsets to maximum if too high */
1480 if (var->xoffset > var->xres_virtual - var->xres)
1481 var->xoffset = var->xres_virtual - var->xres - 1;
1483 if (var->yoffset > var->yres_virtual - var->yres)
1484 var->yoffset = var->yres_virtual - var->yres - 1;
1486 /* Set everything else to 0 */
1487 var->red.msb_right =
1488 var->green.msb_right =
1489 var->blue.msb_right =
1490 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1492 DEBUGPRN("end of check_var");
1497 static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1498 struct fb_info* info)
1502 // printk("\nInside pan_display:");
1504 if (var->xoffset > (var->xres_virtual - var->xres))
1506 if (var->yoffset > (var->yres_virtual - var->yres))
1509 if (var->vmode & FB_VMODE_YWRAP) {
1510 if (var->yoffset < 0
1511 || var->yoffset >= info->var.yres_virtual
1512 || var->xoffset) return -EINVAL;
1514 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1515 var->yoffset + info->var.yres > info->var.yres_virtual)
1519 if((err = XGIfb_pan_var(var)) < 0) return err;
1521 info->var.xoffset = var->xoffset;
1522 info->var.yoffset = var->yoffset;
1523 if (var->vmode & FB_VMODE_YWRAP)
1524 info->var.vmode |= FB_VMODE_YWRAP;
1526 info->var.vmode &= ~FB_VMODE_YWRAP;
1528 // printk(" End of pan_display");
1534 static int XGIfb_blank(int blank, struct fb_info *info)
1538 inXGIIDXREG(XGICR, 0x17, reg);
1545 outXGIIDXREG(XGICR, 0x17, reg);
1546 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1547 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1552 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1555 DEBUGPRN("inside ioctl");
1558 if (!capable(CAP_SYS_RAWIO))
1560 XGI_malloc((struct XGI_memreq *) arg);
1563 if (!capable(CAP_SYS_RAWIO))
1565 XGI_free(*(unsigned long *) arg);
1567 case FBIOGET_HWCINFO:
1569 unsigned long *hwc_offset = (unsigned long *) arg;
1571 if (XGIfb_caps & HW_CURSOR_CAP)
1572 *hwc_offset = XGIfb_hwcursor_vbase -
1573 (unsigned long) xgi_video_info.video_vbase;
1579 case FBIOPUT_MODEINFO:
1581 struct mode_info *x = (struct mode_info *)arg;
1583 xgi_video_info.video_bpp = x->bpp;
1584 xgi_video_info.video_width = x->xres;
1585 xgi_video_info.video_height = x->yres;
1586 xgi_video_info.video_vwidth = x->v_xres;
1587 xgi_video_info.video_vheight = x->v_yres;
1588 xgi_video_info.org_x = x->org_x;
1589 xgi_video_info.org_y = x->org_y;
1590 xgi_video_info.refresh_rate = x->vrate;
1591 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1592 switch(xgi_video_info.video_bpp) {
1594 xgi_video_info.DstColor = 0x0000;
1595 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1596 xgi_video_info.video_cmap_len = 256;
1599 xgi_video_info.DstColor = 0x8000;
1600 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1601 xgi_video_info.video_cmap_len = 16;
1604 xgi_video_info.DstColor = 0xC000;
1605 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1606 xgi_video_info.video_cmap_len = 16;
1609 xgi_video_info.video_cmap_len = 16;
1610 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1611 xgi_video_info.accel = 0;
1617 case FBIOGET_DISPINFO:
1618 XGI_dispinfo((struct ap_data *)arg);
1620 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1622 struct XGIfb_info *x = (struct XGIfb_info *)arg;
1624 //x->XGIfb_id = XGIFB_ID;
1625 x->XGIfb_version = VER_MAJOR;
1626 x->XGIfb_revision = VER_MINOR;
1627 x->XGIfb_patchlevel = VER_LEVEL;
1628 x->chip_id = xgi_video_info.chip_id;
1629 x->memory = xgi_video_info.video_size / 1024;
1630 x->heapstart = xgi_video_info.heapstart / 1024;
1631 x->fbvidmode = XGIfb_mode_no;
1632 x->XGIfb_caps = XGIfb_caps;
1633 x->XGIfb_tqlen = 512; /* yet unused */
1634 x->XGIfb_pcibus = xgi_video_info.pcibus;
1635 x->XGIfb_pcislot = xgi_video_info.pcislot;
1636 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1637 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1638 x->XGIfb_lcda = XGIfb_detectedlcda;
1641 case XGIFB_GET_VBRSTATUS:
1643 unsigned long *vbrstatus = (unsigned long *) arg;
1644 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1645 else *vbrstatus = 0;
1650 DEBUGPRN("end of ioctl");
1657 /* ----------- FBDev related routines for all series ---------- */
1659 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1660 struct fb_info *info)
1662 DEBUGPRN("inside get_fix");
1663 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1665 strcpy(fix->id, myid);
1667 fix->smem_start = xgi_video_info.video_base;
1669 fix->smem_len = xgi_video_info.video_size;
1672 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1673 if (xgi_video_info.video_size > 0x1000000) {
1674 fix->smem_len = 0xD00000;
1675 } else if (xgi_video_info.video_size > 0x800000)
1676 fix->smem_len = 0x800000;
1678 fix->smem_len = 0x400000;
1680 fix->smem_len = XGIfb_mem * 1024;
1682 fix->type = video_type;
1684 if(xgi_video_info.video_bpp == 8)
1685 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1687 fix->visual = FB_VISUAL_DIRECTCOLOR;
1690 if(XGIfb_ypan) fix->ypanstep = 1;
1693 fix->line_length = xgi_video_info.video_linelength;
1694 fix->mmio_start = xgi_video_info.mmio_base;
1695 fix->mmio_len = XGIfb_mmio_size;
1696 if(xgi_video_info.chip >= XG40)
1697 fix->accel = FB_ACCEL_XGI_XABRE;
1699 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1702 DEBUGPRN("end of get_fix");
1707 static struct fb_ops XGIfb_ops = {
1708 .owner = THIS_MODULE,
1709 .fb_open = XGIfb_open,
1710 .fb_release = XGIfb_release,
1711 .fb_check_var = XGIfb_check_var,
1712 .fb_set_par = XGIfb_set_par,
1713 .fb_setcolreg = XGIfb_setcolreg,
1715 .fb_pan_display = XGIfb_pan_display,
1717 .fb_blank = XGIfb_blank,
1718 .fb_fillrect = fbcon_XGI_fillrect,
1719 .fb_copyarea = fbcon_XGI_copyarea,
1720 .fb_imageblit = cfb_imageblit,
1721 .fb_sync = fbcon_XGI_sync,
1722 .fb_ioctl = XGIfb_ioctl,
1723 // .fb_mmap = XGIfb_mmap,
1726 /* ---------------- Chip generation dependent routines ---------------- */
1729 /* for XGI 315/550/650/740/330 */
1731 static int XGIfb_get_dram_size(void)
1737 /* xorg driver sets 32MB * 1 channel */
1738 if (xgi_video_info.chip == XG27)
1739 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1741 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1742 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1743 case XGI_DRAM_SIZE_1MB:
1744 xgi_video_info.video_size = 0x100000;
1746 case XGI_DRAM_SIZE_2MB:
1747 xgi_video_info.video_size = 0x200000;
1749 case XGI_DRAM_SIZE_4MB:
1750 xgi_video_info.video_size = 0x400000;
1752 case XGI_DRAM_SIZE_8MB:
1753 xgi_video_info.video_size = 0x800000;
1755 case XGI_DRAM_SIZE_16MB:
1756 xgi_video_info.video_size = 0x1000000;
1758 case XGI_DRAM_SIZE_32MB:
1759 xgi_video_info.video_size = 0x2000000;
1761 case XGI_DRAM_SIZE_64MB:
1762 xgi_video_info.video_size = 0x4000000;
1764 case XGI_DRAM_SIZE_128MB:
1765 xgi_video_info.video_size = 0x8000000;
1767 case XGI_DRAM_SIZE_256MB:
1768 xgi_video_info.video_size = 0x10000000;
1774 tmp = (reg & 0x0c) >> 2;
1775 switch(xgi_video_info.chip)
1816 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1817 //PLiad fixed for benchmarking and fb set
1818 //xgi_video_info.video_size = 0x200000;//1024x768x16
1819 //xgi_video_info.video_size = 0x1000000;//benchmark
1821 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1826 static void XGIfb_detect_VB(void)
1830 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1832 switch(xgi_video_info.hasVB) {
1833 case HASVB_LVDS_CHRONTEL:
1834 case HASVB_CHRONTEL:
1838 // XGI_Sense30x(); //Yi-Lin TV Sense?
1842 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1844 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1853 if (XGIfb_crt2type != -1)
1854 /* TW: Override with option */
1855 xgi_video_info.disp_state = XGIfb_crt2type;
1856 else if (cr32 & XGI_VB_TV)
1857 xgi_video_info.disp_state = DISPTYPE_TV;
1858 else if (cr32 & XGI_VB_LCD)
1859 xgi_video_info.disp_state = DISPTYPE_LCD;
1860 else if (cr32 & XGI_VB_CRT2)
1861 xgi_video_info.disp_state = DISPTYPE_CRT2;
1863 xgi_video_info.disp_state = 0;
1865 if(XGIfb_tvplug != -1)
1866 /* PR/TW: Override with option */
1867 xgi_video_info.TV_plug = XGIfb_tvplug;
1868 else if (cr32 & XGI_VB_HIVISION) {
1869 xgi_video_info.TV_type = TVMODE_HIVISION;
1870 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1872 else if (cr32 & XGI_VB_SVIDEO)
1873 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1874 else if (cr32 & XGI_VB_COMPOSITE)
1875 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1876 else if (cr32 & XGI_VB_SCART)
1877 xgi_video_info.TV_plug = TVPLUG_SCART;
1879 if(xgi_video_info.TV_type == 0) {
1880 /* TW: PAL/NTSC changed for 650 */
1881 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1883 inXGIIDXREG(XGICR, 0x38, temp);
1885 xgi_video_info.TV_type = TVMODE_PAL;
1887 xgi_video_info.TV_type = TVMODE_NTSC;
1891 inXGIIDXREG(XGICR, 0x79, temp);
1893 xgi_video_info.TV_type = TVMODE_PAL;
1895 xgi_video_info.TV_type = TVMODE_NTSC;
1899 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1900 if (XGIfb_forcecrt1 != -1) {
1901 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1902 else XGIfb_crt1off = 1;
1906 static void XGIfb_get_VB_type(void)
1910 if (!XGIfb_has_VB()) {
1911 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1912 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1913 case XGI310_EXTERNAL_CHIP_LVDS:
1914 xgi_video_info.hasVB = HASVB_LVDS;
1916 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1917 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1926 static int XGIfb_has_VB(void)
1930 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1931 switch (vb_chipid) {
1933 xgi_video_info.hasVB = HASVB_301;
1936 xgi_video_info.hasVB = HASVB_302;
1939 xgi_video_info.hasVB = HASVB_NONE;
1947 /* ------------------ Sensing routines ------------------ */
1949 /* TW: Determine and detect attached devices on XGI30x */
1951 XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1955 outXGIIDXREG(XGIPART4,0x11,tempbl);
1956 temp = tempbh | tempcl;
1957 setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
1958 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
1960 inXGIIDXREG(XGIPART4,0x03,temp);
1970 u8 testsvhs_tempbl, testsvhs_tempbh;
1971 u8 testsvhs_tempcl, testsvhs_tempch;
1972 u8 testcvbs_tempbl, testcvbs_tempbh;
1973 u8 testcvbs_tempcl, testcvbs_tempch;
1974 u8 testvga2_tempbl, testvga2_tempbh;
1975 u8 testvga2_tempcl, testvga2_tempch;
1978 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
1979 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
1983 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
1984 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
1985 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
1986 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
1987 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
1988 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
1989 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
1990 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
1991 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
1992 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
1993 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
1994 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
1995 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
1998 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
1999 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
2000 inXGIIDXREG(XGIPART4,0x01,myflag);
2002 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
2003 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
2004 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2007 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2008 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2009 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2010 testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2011 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2012 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2014 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2015 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2016 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2020 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2021 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2022 testvga2_tempcl, testvga2_tempch);
2024 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2025 orXGIIDXREG(XGICR, 0x32, 0x10);
2029 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2030 testsvhs_tempcl, testsvhs_tempch);
2032 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2033 /* TW: So we can be sure that there IS a SVHS output */
2034 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2035 orXGIIDXREG(XGICR, 0x32, 0x02);
2039 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2040 testcvbs_tempcl, testcvbs_tempch);
2042 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2043 /* TW: So we can be sure that there IS a CVBS output */
2044 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2045 orXGIIDXREG(XGICR, 0x32, 0x01);
2048 XGIDoSense(0, 0, 0, 0);
2050 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2055 /* ------------------------ Heap routines -------------------------- */
2057 static int XGIfb_heap_init(void)
2062 int agp_enabled = 1;
2064 unsigned long *cmdq_baseport = NULL;
2065 unsigned long *read_port = NULL;
2066 unsigned long *write_port = NULL;
2067 XGI_CMDTYPE cmd_type;
2069 struct agp_kern_info *agp_info;
2070 struct agp_memory *agp;
2074 /* TW: The heap start is either set manually using the "mem" parameter, or
2075 * defaults as follows:
2076 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2077 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2078 * -) If 4MB or less is available, let it start at 4MB.
2079 * This is for avoiding a clash with X driver which uses the beginning
2080 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2082 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2083 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2085 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2086 if (xgi_video_info.video_size > 0x1000000) {
2087 xgi_video_info.heapstart = 0xD00000;
2088 } else if (xgi_video_info.video_size > 0x800000) {
2089 xgi_video_info.heapstart = 0x800000;
2091 xgi_video_info.heapstart = 0x400000;
2094 xgi_video_info.heapstart = XGIfb_mem * 1024;
2097 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2098 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2099 (int)(xgi_video_info.heapstart / 1024));
2101 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2102 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2106 /* TW: Now initialize the 310 series' command queue mode.
2107 * On 310/325, there are three queue modes available which
2108 * are chosen by setting bits 7:5 in SR26:
2109 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2110 * track of the queue, the FIFO, command parsing and so
2111 * on. This is the one comparable to the 300 series.
2112 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2113 * have to do queue management himself. Register 0x85c4 will
2114 * hold the location of the next free queue slot, 0x85c8
2115 * is the "queue read pointer" whose way of working is
2116 * unknown to me. Anyway, this mode would require a
2117 * translation of the MMIO commands to some kind of
2118 * accelerator assembly and writing these commands
2119 * to the memory location pointed to by 0x85c4.
2120 * We will not use this, as nobody knows how this
2121 * "assembly" works, and as it would require a complete
2122 * re-write of the accelerator code.
2123 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2124 * queue in AGP memory space.
2126 * SR26 bit 4 is called "Bypass H/W queue".
2127 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2128 * SR26 bit 0 resets the queue
2129 * Size of queue memory is encoded in bits 3:2 like this:
2134 * The queue location is to be written to 0x85C0.
2137 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2138 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2139 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2141 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2143 agp_size = COMMAND_QUEUE_AREA_SIZE;
2146 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2147 agp_info = vmalloc(sizeof(*agp_info));
2148 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2149 agp_copy_info(agp_info);
2151 agp_backend_acquire();
2153 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2156 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2159 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2160 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2161 /* TODO: Free AGP memory here */
2172 /* TW: Now select the queue mode */
2174 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2175 cmd_type = AGP_CMD_QUEUE;
2176 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2177 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2178 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2179 cmd_type = VM_CMD_QUEUE;
2180 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2182 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2183 cmd_type = MMIO_CMD;
2188 temp = XGI_CMD_QUEUE_SIZE_512k;
2191 temp = XGI_CMD_QUEUE_SIZE_1M;
2194 temp = XGI_CMD_QUEUE_SIZE_2M;
2197 temp = XGI_CMD_QUEUE_SIZE_4M;
2204 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2205 agp_info->aper_base, agp->physical, agp_size/1024);
2207 agp_phys = agp_info->aper_base + agp->physical;
2209 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2210 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2212 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2214 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2216 *write_port = *read_port;
2218 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2219 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2221 *cmdq_baseport = agp_phys;
2223 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2228 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2229 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2231 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2233 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2235 *write_port = *read_port;
2237 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2238 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2240 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2242 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2244 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2245 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2250 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2251 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2252 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2253 * enough. Reserve memory in any way.
2255 // FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2256 // FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2258 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2259 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2261 // FIXME *write_port = *read_port;
2263 // FIXME /* TW: Set Auto_Correction bit */
2264 // FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2265 // FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2267 // FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2269 // FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2271 // FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2272 // FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2279 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2280 top of the videoRAM, right below the TB memory area (if used). */
2281 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2282 XGIfb_heap_end -= XGIfb_hwcursor_size;
2283 XGIfb_heap_size -= XGIfb_hwcursor_size;
2284 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2286 XGIfb_caps |= HW_CURSOR_CAP;
2288 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2289 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2292 XGIfb_heap.poha_chain = NULL;
2293 XGIfb_heap.poh_freelist = NULL;
2295 poh = XGIfb_poh_new_node();
2297 if(poh == NULL) return 1;
2299 poh->poh_next = &XGIfb_heap.oh_free;
2300 poh->poh_prev = &XGIfb_heap.oh_free;
2301 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2302 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2304 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2305 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2306 (unsigned int) poh->size / 1024);
2308 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2309 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2311 XGIfb_heap.oh_free.poh_next = poh;
2312 XGIfb_heap.oh_free.poh_prev = poh;
2313 XGIfb_heap.oh_free.size = 0;
2314 XGIfb_heap.max_freesize = poh->size;
2316 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2317 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2318 XGIfb_heap.oh_used.size = SENTINEL;
2323 static XGI_OH *XGIfb_poh_new_node(void)
2330 if (XGIfb_heap.poh_freelist == NULL) {
2331 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2332 if(!poha) return NULL;
2334 poha->poha_next = XGIfb_heap.poha_chain;
2335 XGIfb_heap.poha_chain = poha;
2337 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2339 poh = &poha->aoh[0];
2340 for (i = cOhs - 1; i != 0; i--) {
2341 poh->poh_next = poh + 1;
2345 poh->poh_next = NULL;
2346 XGIfb_heap.poh_freelist = &poha->aoh[0];
2349 poh = XGIfb_heap.poh_freelist;
2350 XGIfb_heap.poh_freelist = poh->poh_next;
2355 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2361 if (size > XGIfb_heap.max_freesize) {
2362 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2363 (unsigned int) size / 1024);
2367 pohThis = XGIfb_heap.oh_free.poh_next;
2369 while (pohThis != &XGIfb_heap.oh_free) {
2370 if (size <= pohThis->size) {
2374 pohThis = pohThis->poh_next;
2378 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2379 (unsigned int) size / 1024);
2383 if (size == pohThis->size) {
2385 XGIfb_delete_node(pohThis);
2387 pohRoot = XGIfb_poh_new_node();
2389 if (pohRoot == NULL) {
2393 pohRoot->offset = pohThis->offset;
2394 pohRoot->size = size;
2396 pohThis->offset += size;
2397 pohThis->size -= size;
2400 XGIfb_heap.max_freesize -= size;
2402 pohThis = &XGIfb_heap.oh_used;
2403 XGIfb_insert_node(pohThis, pohRoot);
2408 static void XGIfb_delete_node(XGI_OH *poh)
2413 poh_prev = poh->poh_prev;
2414 poh_next = poh->poh_next;
2416 poh_prev->poh_next = poh_next;
2417 poh_next->poh_prev = poh_prev;
2421 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2425 pohTemp = pohList->poh_next;
2427 pohList->poh_next = poh;
2428 pohTemp->poh_prev = poh;
2430 poh->poh_prev = pohList;
2431 poh->poh_next = pohTemp;
2434 static XGI_OH *XGIfb_poh_free(unsigned long base)
2440 unsigned long ulUpper;
2441 unsigned long ulLower;
2444 poh_freed = XGIfb_heap.oh_used.poh_next;
2446 while(poh_freed != &XGIfb_heap.oh_used) {
2447 if(poh_freed->offset == base) {
2452 poh_freed = poh_freed->poh_next;
2455 if (!foundNode) return (NULL);
2457 XGIfb_heap.max_freesize += poh_freed->size;
2459 poh_prev = poh_next = NULL;
2460 ulUpper = poh_freed->offset + poh_freed->size;
2461 ulLower = poh_freed->offset;
2463 pohThis = XGIfb_heap.oh_free.poh_next;
2465 while (pohThis != &XGIfb_heap.oh_free) {
2466 if (pohThis->offset == ulUpper) {
2469 else if ((pohThis->offset + pohThis->size) ==
2473 pohThis = pohThis->poh_next;
2476 XGIfb_delete_node(poh_freed);
2478 if (poh_prev && poh_next) {
2479 poh_prev->size += (poh_freed->size + poh_next->size);
2480 XGIfb_delete_node(poh_next);
2481 XGIfb_free_node(poh_freed);
2482 XGIfb_free_node(poh_next);
2487 poh_prev->size += poh_freed->size;
2488 XGIfb_free_node(poh_freed);
2493 poh_next->size += poh_freed->size;
2494 poh_next->offset = poh_freed->offset;
2495 XGIfb_free_node(poh_freed);
2499 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2504 static void XGIfb_free_node(XGI_OH *poh)
2506 if(poh == NULL) return;
2508 poh->poh_next = XGIfb_heap.poh_freelist;
2509 XGIfb_heap.poh_freelist = poh;
2513 void XGI_malloc(struct XGI_memreq *req)
2517 poh = XGIfb_poh_allocate(req->size);
2522 DPRINTK("XGIfb: Video RAM allocation failed\n");
2524 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2525 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2527 req->offset = poh->offset;
2528 req->size = poh->size;
2533 void XGI_free(unsigned long base)
2537 poh = XGIfb_poh_free(base);
2540 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2541 (unsigned int) base);
2545 /* --------------------- SetMode routines ------------------------- */
2547 static void XGIfb_pre_setmode(void)
2549 u8 cr30 = 0, cr31 = 0;
2551 inXGIIDXREG(XGICR, 0x31, cr31);
2554 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2556 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2557 cr31 |= XGI_DRIVER_MODE;
2560 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2561 cr31 |= XGI_DRIVER_MODE;
2564 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2565 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2566 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2567 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2568 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2569 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2570 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2571 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2572 cr31 |= XGI_DRIVER_MODE;
2574 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2579 default: /* disable CRT2 */
2581 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2584 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2585 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2586 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2588 if(xgi_video_info.accel) XGIfb_syncaccel();
2593 static void XGIfb_post_setmode(void)
2596 unsigned char doit = 1;
2597 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2598 outXGIIDXREG(XGICR,0x13,0x00);
2599 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2601 if (xgi_video_info.video_bpp == 8) {
2602 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2603 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2606 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2607 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2612 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2613 if(xgi_video_info.hasVB != HASVB_NONE) {
2614 inXGIIDXREG(XGIPART1, 0x00, reg);
2617 if ((reg & 0x50) == 0x10)
2624 inXGIIDXREG(XGICR, 0x17, reg);
2625 if ((XGIfb_crt1off) && (doit))
2629 outXGIIDXREG(XGICR, 0x17, reg);
2631 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2633 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2635 inXGIIDXREG(XGIPART4, 0x01, reg);
2637 if(reg < 0xB0) { /* Set filter for XGI301 */
2639 switch (xgi_video_info.video_width) {
2641 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2644 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2647 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2650 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2657 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2659 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2661 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2663 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2665 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2667 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2669 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2671 switch (xgi_video_info.video_width) {
2673 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2674 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2675 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2676 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2679 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2680 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2681 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2682 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2685 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2686 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2687 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2688 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2693 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2695 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2697 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2699 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2701 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2703 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2705 switch (xgi_video_info.video_width) {
2707 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2708 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2709 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2710 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2713 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2714 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2715 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2716 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2719 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2720 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2721 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2722 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2728 if ((filter >= 0) && (filter <=7)) {
2729 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2730 XGI_TV_filter[filter_tb].filter[filter][0],
2731 XGI_TV_filter[filter_tb].filter[filter][1],
2732 XGI_TV_filter[filter_tb].filter[filter][2],
2733 XGI_TV_filter[filter_tb].filter[filter][3]
2735 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2736 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2737 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2738 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2748 XGIINITSTATIC int __init XGIfb_setup(char *options)
2754 xgi_video_info.refresh_rate = 0;
2756 printk(KERN_INFO "XGIfb: Options %s\n", options);
2758 if (!options || !*options)
2761 while((this_opt = strsep(&options, ",")) != NULL) {
2763 if (!*this_opt) continue;
2765 if (!strncmp(this_opt, "mode:", 5)) {
2766 XGIfb_search_mode(this_opt + 5);
2767 } else if (!strncmp(this_opt, "vesa:", 5)) {
2768 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2769 } else if (!strncmp(this_opt, "mode:", 5)) {
2770 XGIfb_search_mode(this_opt + 5);
2771 } else if (!strncmp(this_opt, "vesa:", 5)) {
2772 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2773 } else if (!strncmp(this_opt, "vrate:", 6)) {
2774 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2775 } else if (!strncmp(this_opt, "rate:", 5)) {
2776 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2777 } else if (!strncmp(this_opt, "off", 3)) {
2779 } else if (!strncmp(this_opt, "crt1off", 7)) {
2781 } else if (!strncmp(this_opt, "filter:", 7)) {
2782 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2783 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2784 XGIfb_search_crt2type(this_opt + 14);
2785 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2786 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2787 } else if (!strncmp(this_opt, "tvmode:",7)) {
2788 XGIfb_search_tvstd(this_opt + 7);
2789 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2790 XGIfb_search_tvstd(this_opt + 7);
2791 } else if (!strncmp(this_opt, "mem:",4)) {
2792 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2793 } else if (!strncmp(this_opt, "dstn", 4)) {
2795 /* TW: DSTN overrules forcecrt2type */
2796 XGIfb_crt2type = DISPTYPE_LCD;
2797 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2798 XGIfb_search_queuemode(this_opt + 10);
2799 } else if (!strncmp(this_opt, "pdc:", 4)) {
2800 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2801 if(XGIfb_pdc & ~0x3c) {
2802 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2805 } else if (!strncmp(this_opt, "noaccel", 7)) {
2807 } else if (!strncmp(this_opt, "noypan", 6)) {
2809 } else if (!strncmp(this_opt, "userom:", 7)) {
2810 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2811 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2812 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2814 XGIfb_search_mode(this_opt);
2815 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2818 /* TW: Acceleration only with MMIO mode */
2819 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2823 /* TW: Panning only with acceleration */
2824 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2827 printk("\nxgifb: outa xgifb_setup 3450");
2832 static unsigned char VBIOS_BUF[65535];
2834 static unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
2837 u32 rom_address = 0;
2840 /* Get the size of the expansion rom */
2841 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2842 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2843 if ((rom_size & 0x01) == 0)
2849 rom_size &= 0xFFFFF800;
2850 rom_size = (~rom_size)+1;
2852 rom_address = pci_resource_start(dev, 0);
2853 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2855 printk("No suitable rom address found\n"); return NULL;
2858 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2861 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2863 /* memcpy(copy_address, rom_address, rom_size); */
2865 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2867 unsigned char *from = (unsigned char *)virt_addr;
2868 unsigned char *to = (unsigned char *)copy_address;
2869 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2872 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2874 printk("Copy is done\n");
2876 return copy_address;
2879 static int __devinit xgifb_probe(struct pci_dev *pdev,
2880 const struct pci_device_id *ent)
2888 XGIfb_registered = 0;
2890 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2891 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2892 if(!fb_info) return -ENOMEM;
2894 xgi_video_info.chip_id = pdev->device;
2895 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2896 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2897 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2898 XGIvga_enabled = reg16 & 0x01;
2900 xgi_video_info.pcibus = pdev->bus->number;
2901 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2902 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2903 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2904 xgi_video_info.subsysdevice = pdev->subsystem_device;
2906 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2907 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2908 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2909 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2910 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2911 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2912 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2913 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2915 if (pci_enable_device(pdev))
2918 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2920 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2921 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2923 if(reg1 != 0xa1) /*I/O error */
2925 printk("\nXGIfb: I/O error!!!");
2929 switch (xgi_video_info.chip_id) {
2930 case PCI_DEVICE_ID_XG_20:
2931 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2932 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2933 if (CR48&GPIOG_READ)
2934 xgi_video_info.chip = XG21;
2936 xgi_video_info.chip = XG20;
2937 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2938 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2940 case PCI_DEVICE_ID_XG_40:
2941 xgi_video_info.chip = XG40;
2942 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2943 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2945 case PCI_DEVICE_ID_XG_41:
2946 xgi_video_info.chip = XG41;
2947 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2948 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2950 case PCI_DEVICE_ID_XG_42:
2951 xgi_video_info.chip = XG42;
2952 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2953 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2955 case PCI_DEVICE_ID_XG_27:
2956 xgi_video_info.chip = XG27;
2957 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2958 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2964 printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
2965 XGIhw_ext.jChipType = xgi_video_info.chip;
2967 switch (xgi_video_info.chip) {
2975 XGIhw_ext.bIntegratedMMEnabled = 1;
2983 XGIhw_ext.pDevice = NULL;
2984 if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
2986 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
2988 if(XGIhw_ext.pjVirtualRomBase)
2989 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
2991 printk(KERN_INFO "XGIfb: Video ROM not found\n");
2993 XGIhw_ext.pjVirtualRomBase = NULL;
2994 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2996 XGIhw_ext.pjCustomizedROMImage = NULL;
2997 XGIhw_ext.bSkipDramSizing = 0;
2998 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2999 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
3000 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3003 XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
3004 if (XGIhw_ext.pSR == NULL)
3006 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3009 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3011 XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
3012 if (XGIhw_ext.pCR == NULL)
3014 vfree(XGIhw_ext.pSR);
3015 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3018 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3023 if (!XGIvga_enabled)
3025 /* Mapping Max FB Size for 315 Init */
3026 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3027 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3030 printk("XGIfb: XGIInit() ...");
3031 /* XGIInitNewt for LINUXBIOS only */
3032 if(XGIInitNew(&XGIhw_ext))
3042 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3050 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3051 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3054 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3056 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3057 // Set SR13 ,14 temporarily for UDtech
3058 outXGIIDXREG(XGISR, 0x13, 0x45);
3059 outXGIIDXREG(XGISR, 0x14, 0x51);
3065 if (XGIfb_get_dram_size())
3067 vfree(XGIhw_ext.pSR);
3068 vfree(XGIhw_ext.pCR);
3069 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3075 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3077 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3078 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3079 /* Enable 2D accelerator engine */
3080 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3083 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3085 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3086 { printk("unable request memory size %x",xgi_video_info.video_size);
3087 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3088 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3089 vfree(XGIhw_ext.pSR);
3090 vfree(XGIhw_ext.pCR);
3094 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3096 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3097 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3098 vfree(XGIhw_ext.pSR);
3099 vfree(XGIhw_ext.pCR);
3103 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3104 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3105 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3107 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3108 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3110 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3111 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3112 printk("XGIfb: XGIInitNew() ...");
3113 if(XGIInitNew(&XGIhw_ext))
3122 if(XGIfb_heap_init())
3124 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3128 xgi_video_info.mtrr = (unsigned int) 0;
3130 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3132 xgi_video_info.hasVB = HASVB_NONE;
3133 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3134 xgi_video_info.hasVB = HASVB_NONE;
3135 else if(xgi_video_info.chip == XG21) {
3136 inXGIIDXREG(XGICR,0x38,CR38);
3137 if ((CR38&0xE0) == 0xC0) {
3138 xgi_video_info.disp_state = DISPTYPE_LCD;
3139 if (!XGIfb_GetXG21LVDSData()) {
3141 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3142 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3143 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3144 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3149 else if ((CR38&0xE0) == 0x60)
3150 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3152 xgi_video_info.hasVB = HASVB_NONE;
3155 XGIfb_get_VB_type();
3157 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3159 XGIhw_ext.ulExternalChip = 0;
3161 switch (xgi_video_info.hasVB) {
3163 inXGIIDXREG(XGIPART4, 0x01, reg);
3165 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3166 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3167 } else if (reg >= 0xD0) {
3168 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3169 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3171 /* else if (reg >= 0xB0) {
3172 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3173 inXGIIDXREG(XGIPART4,0x23,reg1);
3174 printk("XGIfb: XGI301B bridge detected\n");
3177 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3178 printk("XGIfb: XGI301 bridge detected\n");
3182 inXGIIDXREG(XGIPART4, 0x01, reg);
3184 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3185 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3186 } else if (reg >= 0xD0) {
3187 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3188 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3189 } else if (reg >= 0xB0) {
3190 inXGIIDXREG(XGIPART4,0x23,reg1);
3192 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3195 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3196 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3200 XGIhw_ext.ulExternalChip = 0x1;
3201 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3203 case HASVB_TRUMPION:
3204 XGIhw_ext.ulExternalChip = 0x2;
3205 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3207 case HASVB_CHRONTEL:
3208 XGIhw_ext.ulExternalChip = 0x4;
3209 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3211 case HASVB_LVDS_CHRONTEL:
3212 XGIhw_ext.ulExternalChip = 0x5;
3213 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3216 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3220 if (xgi_video_info.hasVB != HASVB_NONE) {
3224 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3226 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3228 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3230 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3233 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3235 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3237 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3241 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3245 XGIfb_detectedpdc = 0;
3247 XGIfb_detectedlcda = 0xff;
3250 /* TW: Try to find about LCDA */
3252 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3253 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3254 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3257 inXGIIDXREG(XGICR,0x34,tmp);
3260 // Currently on LCDA? (Some BIOSes leave CR38)
3261 inXGIIDXREG(XGICR,0x38,tmp);
3262 if((tmp & 0x03) == 0x03)
3264 /* XGI_Pr.XGI_UseLCDA = 1; */
3267 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3268 inXGIIDXREG(XGICR,0x35,tmp);
3271 /* XGI_Pr.XGI_UseLCDA = 1; */
3274 inXGIIDXREG(XGICR,0x30,tmp);
3277 inXGIIDXREG(XGIPART1,0x13,tmp);
3280 /* XGI_Pr.XGI_UseLCDA = 1; */
3292 if (xgifb_mode_idx >= 0)
3293 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3295 if (xgifb_mode_idx < 0) {
3296 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3298 xgifb_mode_idx = DEFAULT_LCDMODE;
3299 if (xgi_video_info.chip == XG21)
3301 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3305 xgifb_mode_idx = DEFAULT_TVMODE;
3308 xgifb_mode_idx = DEFAULT_MODE;
3313 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3316 if( xgi_video_info.refresh_rate == 0)
3317 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3318 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3320 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3321 xgi_video_info.refresh_rate = 60;
3324 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3325 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3326 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3327 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3328 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3329 switch(xgi_video_info.video_bpp) {
3331 xgi_video_info.DstColor = 0x0000;
3332 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3333 xgi_video_info.video_cmap_len = 256;
3336 xgi_video_info.DstColor = 0x8000;
3337 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3338 xgi_video_info.video_cmap_len = 16;
3341 xgi_video_info.DstColor = 0xC000;
3342 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3343 xgi_video_info.video_cmap_len = 16;
3346 xgi_video_info.video_cmap_len = 16;
3347 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3353 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3354 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3355 xgi_video_info.refresh_rate);
3357 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3358 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3359 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3361 XGIfb_bpp_to_var(&default_var);
3363 default_var.pixclock = (u32) (1000000000 /
3364 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3365 XGIfb_mode_no, XGIfb_rate_idx));
3367 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3368 XGIfb_mode_no, XGIfb_rate_idx,
3369 &default_var.left_margin, &default_var.right_margin,
3370 &default_var.upper_margin, &default_var.lower_margin,
3371 &default_var.hsync_len, &default_var.vsync_len,
3372 &default_var.sync, &default_var.vmode)) {
3374 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3375 default_var.yres <<= 1;
3376 default_var.yres_virtual <<= 1;
3377 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3378 default_var.pixclock >>= 1;
3379 default_var.yres >>= 1;
3380 default_var.yres_virtual >>= 1;
3385 xgi_video_info.accel = 0;
3387 xgi_video_info.accel = -1;
3388 default_var.accel_flags |= FB_ACCELF_TEXT;
3392 fb_info->flags = FBINFO_FLAG_DEFAULT;
3393 fb_info->var = default_var;
3394 fb_info->fix = XGIfb_fix;
3395 fb_info->par = &xgi_video_info;
3396 fb_info->screen_base = xgi_video_info.video_vbase;
3397 fb_info->fbops = &XGIfb_ops;
3398 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3399 fb_info->pseudo_palette = pseudo_palette;
3401 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3405 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3406 (unsigned int) xgi_video_info.video_size,
3407 MTRR_TYPE_WRCOMB, 1);
3408 if(xgi_video_info.mtrr) {
3409 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3413 if(register_framebuffer(fb_info) < 0)
3418 XGIfb_registered = 1;
3420 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
3423 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3424 XGIfb_accel ? "enabled" : "disabled",
3425 XGIfb_ypan ? "ypan" : "redraw");
3427 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3428 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3439 /*****************************************************/
3440 /* PCI DEVICE HANDLING */
3441 /*****************************************************/
3443 static void __devexit xgifb_remove(struct pci_dev *pdev)
3445 /* Unregister the framebuffer */
3446 // if(xgi_video_info.registered) {
3447 unregister_framebuffer(fb_info);
3448 framebuffer_release(fb_info);
3451 pci_set_drvdata(pdev, NULL);
3455 static struct pci_driver xgifb_driver = {
3457 .id_table = xgifb_pci_table,
3458 .probe = xgifb_probe,
3459 .remove = __devexit_p(xgifb_remove)
3462 XGIINITSTATIC int __init xgifb_init(void)
3465 char *option = NULL;
3467 if (fb_get_options("xgifb", &option))
3469 XGIfb_setup(option);
3471 return(pci_register_driver(&xgifb_driver));
3476 module_init(xgifb_init);
3479 /*****************************************************/
3481 /*****************************************************/
3485 static char *mode = NULL;
3486 static int vesa = 0;
3487 static unsigned int rate = 0;
3488 static unsigned int crt1off = 1;
3489 static unsigned int mem = 0;
3490 static char *forcecrt2type = NULL;
3491 static int forcecrt1 = -1;
3492 static int pdc = -1;
3493 static int pdc1 = -1;
3494 static int noaccel = -1;
3495 static int noypan = -1;
3496 static int nomax = -1;
3497 static int userom = -1;
3498 static int useoem = -1;
3499 static char *tvstandard = NULL;
3500 static int nocrt2rate = 0;
3501 static int scalelcd = -1;
3502 static char *specialtiming = NULL;
3503 static int lvdshl = -1;
3504 static int tvxposoffset = 0, tvyposoffset = 0;
3505 #if !defined(__i386__) && !defined(__x86_64__)
3506 static int resetcard = 0;
3507 static int videoram = 0;
3510 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3511 MODULE_LICENSE("GPL");
3512 MODULE_AUTHOR("XGITECH , Others");
3516 module_param(mem, int, 0);
3517 module_param(noaccel, int, 0);
3518 module_param(noypan, int, 0);
3519 module_param(nomax, int, 0);
3520 module_param(userom, int, 0);
3521 module_param(useoem, int, 0);
3522 module_param(mode, charp, 0);
3523 module_param(vesa, int, 0);
3524 module_param(rate, int, 0);
3525 module_param(forcecrt1, int, 0);
3526 module_param(forcecrt2type, charp, 0);
3527 module_param(scalelcd, int, 0);
3528 module_param(pdc, int, 0);
3529 module_param(pdc1, int, 0);
3530 module_param(specialtiming, charp, 0);
3531 module_param(lvdshl, int, 0);
3532 module_param(tvstandard, charp, 0);
3533 module_param(tvxposoffset, int, 0);
3534 module_param(tvyposoffset, int, 0);
3535 module_param(filter, int, 0);
3536 module_param(nocrt2rate, int, 0);
3537 #if !defined(__i386__) && !defined(__x86_64__)
3538 module_param(resetcard, int, 0);
3539 module_param(videoram, int, 0);
3543 MODULE_PARM_DESC(mem,
3544 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3545 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3546 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3547 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3548 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3549 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3550 "for XFree86 4.x/X.org 6.7 and later.\n");
3552 MODULE_PARM_DESC(noaccel,
3553 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3556 MODULE_PARM_DESC(noypan,
3557 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3558 "will be performed by redrawing the screen. (default: 0)\n");
3560 MODULE_PARM_DESC(nomax,
3561 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3562 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3563 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3564 "enable the user to positively specify a virtual Y size of the screen using\n"
3565 "fbset. (default: 0)\n");
3569 MODULE_PARM_DESC(mode,
3570 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3571 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3572 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3573 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3575 MODULE_PARM_DESC(vesa,
3576 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3577 "0x117 (default: 0x0103)\n");
3580 MODULE_PARM_DESC(rate,
3581 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3582 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3583 "will be ignored (default: 60)\n");
3585 MODULE_PARM_DESC(forcecrt1,
3586 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3587 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3588 "0=CRT1 OFF) (default: [autodetected])\n");
3590 MODULE_PARM_DESC(forcecrt2type,
3591 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3592 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3593 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3594 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3595 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3596 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3597 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3598 "depends on the very hardware in use. (default: [autodetected])\n");
3600 MODULE_PARM_DESC(scalelcd,
3601 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3602 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3603 "show black bars around the image, TMDS panels will probably do the scaling\n"
3604 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3606 MODULE_PARM_DESC(pdc,
3607 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3608 "should detect this correctly in most cases; however, sometimes this is not\n"
3609 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3610 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3611 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3612 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3614 MODULE_PARM_DESC(pdc1,
3615 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3616 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3617 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3618 "implemented yet.\n");
3620 MODULE_PARM_DESC(specialtiming,
3621 "\nPlease refer to documentation for more information on this option.\n");
3623 MODULE_PARM_DESC(lvdshl,
3624 "\nPlease refer to documentation for more information on this option.\n");
3626 MODULE_PARM_DESC(tvstandard,
3627 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3628 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3630 MODULE_PARM_DESC(tvxposoffset,
3631 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3634 MODULE_PARM_DESC(tvyposoffset,
3635 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3638 MODULE_PARM_DESC(filter,
3639 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3640 "(Possible values 0-7, default: [no filter])\n");
3642 MODULE_PARM_DESC(nocrt2rate,
3643 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3644 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3649 static int __init xgifb_init_module(void)
3651 printk("\nXGIfb_init_module");
3653 XGIfb_search_mode(mode);
3654 else if (vesa != -1)
3655 XGIfb_search_vesamode(vesa);
3657 return(xgifb_init());
3660 static void __exit xgifb_remove_module(void)
3662 pci_unregister_driver(&xgifb_driver);
3663 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3666 module_init(xgifb_init_module);
3667 module_exit(xgifb_remove_module);
3669 #endif /* /MODULE */
3671 EXPORT_SYMBOL(XGI_malloc);
3672 EXPORT_SYMBOL(XGI_free);