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(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
166 unsigned char modeno, unsigned char rateindex)
168 unsigned short ModeNo = modeno;
169 unsigned short ModeIdIndex = 0, ClockIndex = 0;
170 unsigned short RefreshRateTableIndex = 0;
172 /*unsigned long temp = 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(struct vb_device_info *XGI_Pr, struct xgi_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 unsigned short ModeNo = modeno;
208 unsigned short ModeIdIndex = 0, index = 0;
209 unsigned short 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(struct vb_device_info *XGI_Pr, unsigned long 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(struct xgi_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 /*unsigned char XGIfb_query_north_bridge_space(struct xgi_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 ] ;
614 (k < (sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct))));
620 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
624 int XGIfb_mode_idx = 0;
627 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
628 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
630 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
631 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
632 (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
634 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
643 return (XGIfb_mode_idx);
647 static int XGIfb_validate_mode(int myindex)
651 if (xgi_video_info.chip == XG21)
653 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
655 xres = XGI21_LCDCapList[0].LVDSHDE;
656 yres = XGI21_LCDCapList[0].LVDSVDE;
657 if(XGIbios_mode[myindex].xres > xres)
659 if(XGIbios_mode[myindex].yres > yres)
661 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
663 if (XGIbios_mode[myindex].bpp > 8)
672 /* FIXME: for now, all is valid on XG27 */
673 if (xgi_video_info.chip == XG27)
676 if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
679 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
681 switch (XGIhw_ext.ulCRT2LCDType) {
683 xres = 640; yres = 480; break;
685 xres = 800; yres = 600; break;
687 xres = 1024; yres = 600; break;
689 xres = 1024; yres = 768; break;
691 xres = 1152; yres = 768; break;
693 xres = 1280; yres = 960; break;
695 xres = 1280; yres = 768; break;
697 xres = 1280; yres = 1024; break;
699 xres = 1400; yres = 1050; break;
701 xres = 1600; yres = 1200; break;
702 // case LCD_320x480: // TW: FSTN
703 // xres = 320; yres = 480; break;
705 xres = 0; yres = 0; break;
707 if(XGIbios_mode[myindex].xres > xres) {
710 if(XGIbios_mode[myindex].yres > yres) {
713 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
714 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
716 switch (XGIbios_mode[myindex].xres) {
718 if(XGIbios_mode[myindex].yres != 512) return -1;
719 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
722 if((XGIbios_mode[myindex].yres != 400) &&
723 (XGIbios_mode[myindex].yres != 480))
727 if(XGIbios_mode[myindex].yres != 600) return -1;
730 if((XGIbios_mode[myindex].yres != 600) &&
731 (XGIbios_mode[myindex].yres != 768))
733 if((XGIbios_mode[myindex].yres == 600) &&
734 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
738 if((XGIbios_mode[myindex].yres) != 768) return -1;
739 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
742 if((XGIbios_mode[myindex].yres != 768) &&
743 (XGIbios_mode[myindex].yres != 1024))
745 if((XGIbios_mode[myindex].yres == 768) &&
746 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
750 if(XGIbios_mode[myindex].yres != 1050) return -1;
753 if(XGIbios_mode[myindex].yres != 1200) return -1;
759 switch (XGIbios_mode[myindex].xres) {
761 if(XGIbios_mode[myindex].yres != 512) return -1;
764 if((XGIbios_mode[myindex].yres != 400) &&
765 (XGIbios_mode[myindex].yres != 480))
769 if(XGIbios_mode[myindex].yres != 600) return -1;
772 if(XGIbios_mode[myindex].yres != 768) return -1;
775 if((XGIbios_mode[myindex].yres != 960) &&
776 (XGIbios_mode[myindex].yres != 1024))
778 if(XGIbios_mode[myindex].yres == 960) {
779 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
784 if(XGIbios_mode[myindex].yres != 1050) return -1;
787 if(XGIbios_mode[myindex].yres != 1200) return -1;
795 switch (XGIbios_mode[myindex].xres) {
801 if (xgi_video_info.TV_type == TVMODE_NTSC) {
802 if (XGIbios_mode[myindex].yres != 480) {
805 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
806 if (XGIbios_mode[myindex].yres != 576) {
810 // TW: LVDS/CHRONTEL does not support 720
811 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
812 xgi_video_info.hasVB == HASVB_CHRONTEL) {
817 if (xgi_video_info.TV_type == TVMODE_NTSC) {
818 if(XGIbios_mode[myindex].bpp == 32) {
822 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
823 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
824 xgi_video_info.hasVB == HASVB_CHRONTEL) {
825 if(xgi_video_info.chip < XGI_315H) {
835 if(XGIbios_mode[myindex].xres > 1280) return -1;
842 static void XGIfb_search_crt2type(const char *name)
849 while(XGI_crt2type[i].type_no != -1) {
850 if (!strcmp(name, XGI_crt2type[i].name)) {
851 XGIfb_crt2type = XGI_crt2type[i].type_no;
852 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
857 if(XGIfb_crt2type < 0)
858 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
861 static void XGIfb_search_queuemode(const char *name)
868 while (XGI_queuemode[i].type_no != -1) {
869 if (!strcmp(name, XGI_queuemode[i].name)) {
870 XGIfb_queuemode = XGI_queuemode[i].type_no;
875 if (XGIfb_queuemode < 0)
876 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
879 static u8 XGIfb_search_refresh_rate(unsigned int rate)
884 xres = XGIbios_mode[xgifb_mode_idx].xres;
885 yres = XGIbios_mode[xgifb_mode_idx].yres;
888 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
889 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
890 if (XGIfb_vrate[i].refresh == rate) {
891 XGIfb_rate_idx = XGIfb_vrate[i].idx;
893 } else if (XGIfb_vrate[i].refresh > rate) {
894 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
895 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
896 rate, XGIfb_vrate[i].refresh);
897 XGIfb_rate_idx = XGIfb_vrate[i].idx;
898 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
899 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
900 && (XGIfb_vrate[i].idx != 1)) {
901 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
902 rate, XGIfb_vrate[i-1].refresh);
903 XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
904 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
907 } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
908 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
909 rate, XGIfb_vrate[i].refresh);
910 XGIfb_rate_idx = XGIfb_vrate[i].idx;
916 if (XGIfb_rate_idx > 0) {
917 return XGIfb_rate_idx;
920 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
925 static void XGIfb_search_tvstd(const char *name)
932 while (XGI_tvtype[i].type_no != -1) {
933 if (!strcmp(name, XGI_tvtype[i].name)) {
934 XGIfb_tvmode = XGI_tvtype[i].type_no;
941 static unsigned char XGIfb_bridgeisslave(void)
943 unsigned char usScratchP1_00;
945 if (xgi_video_info.hasVB == HASVB_NONE)
948 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
949 if ((usScratchP1_00 & 0x50) == 0x10)
955 static unsigned char XGIfbcheckvretracecrt1(void)
959 inXGIIDXREG(XGICR,0x17,temp);
964 inXGIIDXREG(XGISR,0x1f,temp);
968 if (inXGIREG(XGIINPSTAT) & 0x08)
974 static unsigned char XGIfbcheckvretracecrt2(void)
977 if (xgi_video_info.hasVB == HASVB_NONE)
979 inXGIIDXREG(XGIPART1, 0x30, temp);
986 static unsigned char XGIfb_CheckVBRetrace(void)
988 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
989 if(XGIfb_bridgeisslave()) {
990 return(XGIfbcheckvretracecrt1());
992 return(XGIfbcheckvretracecrt2());
995 return(XGIfbcheckvretracecrt1());
998 /* ----------- FBDev related routines for all series ----------- */
1001 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1003 switch(var->bits_per_pixel) {
1005 var->red.offset = var->green.offset = var->blue.offset = 0;
1006 var->red.length = var->green.length = var->blue.length = 6;
1007 xgi_video_info.video_cmap_len = 256;
1010 var->red.offset = 11;
1011 var->red.length = 5;
1012 var->green.offset = 5;
1013 var->green.length = 6;
1014 var->blue.offset = 0;
1015 var->blue.length = 5;
1016 var->transp.offset = 0;
1017 var->transp.length = 0;
1018 xgi_video_info.video_cmap_len = 16;
1021 var->red.offset = 16;
1022 var->red.length = 8;
1023 var->green.offset = 8;
1024 var->green.length = 8;
1025 var->blue.offset = 0;
1026 var->blue.length = 8;
1027 var->transp.offset = 24;
1028 var->transp.length = 8;
1029 xgi_video_info.video_cmap_len = 16;
1036 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1037 struct fb_info *info)
1040 unsigned int htotal = var->left_margin + var->xres +
1041 var->right_margin + var->hsync_len;
1042 unsigned int vtotal = var->upper_margin + var->yres +
1043 var->lower_margin + var->vsync_len;
1044 #if defined(__powerpc__)
1045 u8 sr_data, cr_data;
1047 unsigned int drate = 0, hrate = 0;
1050 // unsigned char reg,reg1;
1052 DEBUGPRN("Inside do_set_var");
1053 // 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);
1055 info->var.xres_virtual = var->xres_virtual;
1056 info->var.yres_virtual = var->yres_virtual;
1057 info->var.bits_per_pixel = var->bits_per_pixel;
1059 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1061 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1063 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1069 if(!htotal || !vtotal) {
1070 DPRINTK("XGIfb: Invalid 'var' information\n");
1073 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1074 var->pixclock,htotal,vtotal);
1078 if(var->pixclock && htotal && vtotal) {
1079 drate = 1000000000 / var->pixclock;
1080 hrate = (drate * 1000) / htotal;
1081 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1083 xgi_video_info.refresh_rate = 60;
1086 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1087 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1089 old_mode = xgifb_mode_idx;
1092 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1093 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1094 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1095 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1096 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1097 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1105 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1107 xgifb_mode_idx = -1;
1109 if(xgifb_mode_idx < 0) {
1110 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1111 var->yres, var->bits_per_pixel);
1112 xgifb_mode_idx = old_mode;
1116 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1117 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1118 xgi_video_info.refresh_rate = 60;
1124 XGIfb_pre_setmode();
1125 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1126 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1129 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1131 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1133 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1134 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1136 XGIfb_post_setmode();
1138 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1139 XGIbios_mode[xgifb_mode_idx].xres,
1140 XGIbios_mode[xgifb_mode_idx].yres,
1141 XGIbios_mode[xgifb_mode_idx].bpp,
1142 xgi_video_info.refresh_rate);
1144 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1145 xgi_video_info.video_vwidth = info->var.xres_virtual;
1146 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1147 xgi_video_info.video_vheight = info->var.yres_virtual;
1148 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1149 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1150 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1151 xgi_video_info.accel = 0;
1153 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1155 switch(xgi_video_info.video_bpp)
1158 xgi_video_info.DstColor = 0x0000;
1159 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1160 xgi_video_info.video_cmap_len = 256;
1161 #if defined(__powerpc__)
1162 inXGIIDXREG (XGICR, 0x4D, cr_data);
1163 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1167 xgi_video_info.DstColor = 0x8000;
1168 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1169 #if defined(__powerpc__)
1170 inXGIIDXREG (XGICR, 0x4D, cr_data);
1171 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1173 xgi_video_info.video_cmap_len = 16;
1176 xgi_video_info.DstColor = 0xC000;
1177 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1178 xgi_video_info.video_cmap_len = 16;
1179 #if defined(__powerpc__)
1180 inXGIIDXREG (XGICR, 0x4D, cr_data);
1181 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1185 xgi_video_info.video_cmap_len = 16;
1186 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1187 xgi_video_info.accel = 0;
1191 XGIfb_bpp_to_var(var); /*update ARGB info*/
1192 DEBUGPRN("End of do_set_var");
1199 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1203 // printk("Inside pan_var");
1205 if (var->xoffset > (var->xres_virtual - var->xres)) {
1206 // printk( "Pan: xo: %d xv %d xr %d\n",
1207 // var->xoffset, var->xres_virtual, var->xres);
1210 if(var->yoffset > (var->yres_virtual - var->yres)) {
1211 // printk( "Pan: yo: %d yv %d yr %d\n",
1212 // var->yoffset, var->yres_virtual, var->yres);
1215 base = var->yoffset * var->xres_virtual + var->xoffset;
1217 /* calculate base bpp dep. */
1218 switch(var->bits_per_pixel) {
1230 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1232 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1233 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1234 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1235 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1236 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1238 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1239 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1240 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1241 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1242 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1243 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1245 // printk("End of pan_var");
1251 void XGI_dispinfo(struct ap_data *rec)
1253 rec->minfo.bpp = xgi_video_info.video_bpp;
1254 rec->minfo.xres = xgi_video_info.video_width;
1255 rec->minfo.yres = xgi_video_info.video_height;
1256 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1257 rec->minfo.v_yres = xgi_video_info.video_vheight;
1258 rec->minfo.org_x = xgi_video_info.org_x;
1259 rec->minfo.org_y = xgi_video_info.org_y;
1260 rec->minfo.vrate = xgi_video_info.refresh_rate;
1261 rec->iobase = xgi_video_info.vga_base - 0x30;
1262 rec->mem_size = xgi_video_info.video_size;
1263 rec->disp_state = xgi_video_info.disp_state;
1264 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1265 rec->hasVB = xgi_video_info.hasVB;
1266 rec->TV_type = xgi_video_info.TV_type;
1267 rec->TV_plug = xgi_video_info.TV_plug;
1268 rec->chip = xgi_video_info.chip;
1274 static int XGIfb_open(struct fb_info *info, int user)
1279 static int XGIfb_release(struct fb_info *info, int user)
1284 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1288 switch(var->bits_per_pixel) {
1302 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1303 unsigned transp, struct fb_info *info)
1305 if (regno >= XGIfb_get_cmap_len(&info->var))
1308 switch (info->var.bits_per_pixel) {
1310 outXGIREG(XGIDACA, regno);
1311 outXGIREG(XGIDACD, (red >> 10));
1312 outXGIREG(XGIDACD, (green >> 10));
1313 outXGIREG(XGIDACD, (blue >> 10));
1314 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1315 outXGIREG(XGIDAC2A, regno);
1316 outXGIREG(XGIDAC2D, (red >> 8));
1317 outXGIREG(XGIDAC2D, (green >> 8));
1318 outXGIREG(XGIDAC2D, (blue >> 8));
1322 ((u32 *)(info->pseudo_palette))[regno] =
1323 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1329 ((u32 *) (info->pseudo_palette))[regno] =
1330 (red << 16) | (green << 8) | (blue);
1336 static int XGIfb_set_par(struct fb_info *info)
1340 // printk("XGIfb: inside set_par\n");
1341 if((err = XGIfb_do_set_var(&info->var, 1, info)))
1343 XGIfb_get_fix(&info->fix, -1, info);
1344 // printk("XGIfb:end of set_par\n");
1348 static int XGIfb_check_var(struct fb_var_screeninfo *var,
1349 struct fb_info *info)
1351 unsigned int htotal =
1352 var->left_margin + var->xres + var->right_margin +
1354 unsigned int vtotal = 0;
1355 unsigned int drate = 0, hrate = 0;
1357 int refresh_rate, search_idx;
1359 DEBUGPRN("Inside check_var");
1361 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1362 vtotal = var->upper_margin + var->yres + var->lower_margin +
1365 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1366 vtotal = var->upper_margin + var->yres + var->lower_margin +
1369 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1370 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1372 } else vtotal = var->upper_margin + var->yres + var->lower_margin +
1375 if(!(htotal) || !(vtotal)) {
1376 XGIFAIL("XGIfb: no valid timing data");
1380 if(var->pixclock && htotal && vtotal) {
1381 drate = 1000000000 / var->pixclock;
1382 hrate = (drate * 1000) / htotal;
1383 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1385 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1386 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1387 __func__,var->pixclock, htotal, vtotal,
1388 __func__, drate, hrate, xgi_video_info.refresh_rate);
1390 xgi_video_info.refresh_rate = 60;
1394 if((var->pixclock) && (htotal)) {
1395 drate = 1E12 / var->pixclock;
1396 hrate = drate / htotal;
1397 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1398 } else refresh_rate = 60;
1400 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1401 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1404 while((XGIbios_mode[search_idx].mode_no != 0) &&
1405 (XGIbios_mode[search_idx].xres <= var->xres) ) {
1406 if((XGIbios_mode[search_idx].xres == var->xres) &&
1407 (XGIbios_mode[search_idx].yres == var->yres) &&
1408 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1409 if(XGIfb_validate_mode(search_idx) > 0) {
1419 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1420 var->xres, var->yres, var->bits_per_pixel);
1423 while(XGIbios_mode[search_idx].mode_no != 0) {
1425 if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1426 (var->yres <= XGIbios_mode[search_idx].yres) &&
1427 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1428 if(XGIfb_validate_mode(search_idx) > 0) {
1436 var->xres = XGIbios_mode[search_idx].xres;
1437 var->yres = XGIbios_mode[search_idx].yres;
1438 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1439 var->xres, var->yres, var->bits_per_pixel);
1442 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1443 var->xres, var->yres, var->bits_per_pixel);
1448 /* TW: TODO: Check the refresh rate */
1450 /* Adapt RGB settings */
1451 XGIfb_bpp_to_var(var);
1453 /* Sanity check for offsets */
1454 if (var->xoffset < 0)
1456 if (var->yoffset < 0)
1461 if(var->xres != var->xres_virtual)
1462 var->xres_virtual = var->xres;
1463 if(var->yres != var->yres_virtual)
1464 var->yres_virtual = var->yres;
1466 // TW: Now patch yres_virtual if we use panning
1468 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1469 if(var->yres_virtual <= var->yres) {
1470 // TW: Paranoia check
1471 var->yres_virtual = var->yres;
1475 /* Truncate offsets to maximum if too high */
1476 if (var->xoffset > var->xres_virtual - var->xres)
1477 var->xoffset = var->xres_virtual - var->xres - 1;
1479 if (var->yoffset > var->yres_virtual - var->yres)
1480 var->yoffset = var->yres_virtual - var->yres - 1;
1482 /* Set everything else to 0 */
1483 var->red.msb_right =
1484 var->green.msb_right =
1485 var->blue.msb_right =
1486 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1488 DEBUGPRN("end of check_var");
1493 static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1494 struct fb_info* info)
1498 // printk("\nInside pan_display:");
1500 if (var->xoffset > (var->xres_virtual - var->xres))
1502 if (var->yoffset > (var->yres_virtual - var->yres))
1505 if (var->vmode & FB_VMODE_YWRAP) {
1506 if (var->yoffset < 0
1507 || var->yoffset >= info->var.yres_virtual
1508 || var->xoffset) return -EINVAL;
1510 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1511 var->yoffset + info->var.yres > info->var.yres_virtual)
1515 if((err = XGIfb_pan_var(var)) < 0) return err;
1517 info->var.xoffset = var->xoffset;
1518 info->var.yoffset = var->yoffset;
1519 if (var->vmode & FB_VMODE_YWRAP)
1520 info->var.vmode |= FB_VMODE_YWRAP;
1522 info->var.vmode &= ~FB_VMODE_YWRAP;
1524 // printk(" End of pan_display");
1530 static int XGIfb_blank(int blank, struct fb_info *info)
1534 inXGIIDXREG(XGICR, 0x17, reg);
1541 outXGIIDXREG(XGICR, 0x17, reg);
1542 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1543 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1548 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1551 DEBUGPRN("inside ioctl");
1554 if (!capable(CAP_SYS_RAWIO))
1556 XGI_malloc((struct XGI_memreq *) arg);
1559 if (!capable(CAP_SYS_RAWIO))
1561 XGI_free(*(unsigned long *) arg);
1563 case FBIOGET_HWCINFO:
1565 unsigned long *hwc_offset = (unsigned long *) arg;
1567 if (XGIfb_caps & HW_CURSOR_CAP)
1568 *hwc_offset = XGIfb_hwcursor_vbase -
1569 (unsigned long) xgi_video_info.video_vbase;
1575 case FBIOPUT_MODEINFO:
1577 struct mode_info *x = (struct mode_info *)arg;
1579 xgi_video_info.video_bpp = x->bpp;
1580 xgi_video_info.video_width = x->xres;
1581 xgi_video_info.video_height = x->yres;
1582 xgi_video_info.video_vwidth = x->v_xres;
1583 xgi_video_info.video_vheight = x->v_yres;
1584 xgi_video_info.org_x = x->org_x;
1585 xgi_video_info.org_y = x->org_y;
1586 xgi_video_info.refresh_rate = x->vrate;
1587 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1588 switch(xgi_video_info.video_bpp) {
1590 xgi_video_info.DstColor = 0x0000;
1591 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1592 xgi_video_info.video_cmap_len = 256;
1595 xgi_video_info.DstColor = 0x8000;
1596 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1597 xgi_video_info.video_cmap_len = 16;
1600 xgi_video_info.DstColor = 0xC000;
1601 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1602 xgi_video_info.video_cmap_len = 16;
1605 xgi_video_info.video_cmap_len = 16;
1606 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1607 xgi_video_info.accel = 0;
1613 case FBIOGET_DISPINFO:
1614 XGI_dispinfo((struct ap_data *)arg);
1616 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1618 struct XGIfb_info *x = (struct XGIfb_info *)arg;
1620 //x->XGIfb_id = XGIFB_ID;
1621 x->XGIfb_version = VER_MAJOR;
1622 x->XGIfb_revision = VER_MINOR;
1623 x->XGIfb_patchlevel = VER_LEVEL;
1624 x->chip_id = xgi_video_info.chip_id;
1625 x->memory = xgi_video_info.video_size / 1024;
1626 x->heapstart = xgi_video_info.heapstart / 1024;
1627 x->fbvidmode = XGIfb_mode_no;
1628 x->XGIfb_caps = XGIfb_caps;
1629 x->XGIfb_tqlen = 512; /* yet unused */
1630 x->XGIfb_pcibus = xgi_video_info.pcibus;
1631 x->XGIfb_pcislot = xgi_video_info.pcislot;
1632 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1633 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1634 x->XGIfb_lcda = XGIfb_detectedlcda;
1637 case XGIFB_GET_VBRSTATUS:
1639 unsigned long *vbrstatus = (unsigned long *) arg;
1640 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1641 else *vbrstatus = 0;
1646 DEBUGPRN("end of ioctl");
1653 /* ----------- FBDev related routines for all series ---------- */
1655 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1656 struct fb_info *info)
1658 DEBUGPRN("inside get_fix");
1659 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1661 strcpy(fix->id, myid);
1663 fix->smem_start = xgi_video_info.video_base;
1665 fix->smem_len = xgi_video_info.video_size;
1668 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1669 if (xgi_video_info.video_size > 0x1000000) {
1670 fix->smem_len = 0xD00000;
1671 } else if (xgi_video_info.video_size > 0x800000)
1672 fix->smem_len = 0x800000;
1674 fix->smem_len = 0x400000;
1676 fix->smem_len = XGIfb_mem * 1024;
1678 fix->type = video_type;
1680 if(xgi_video_info.video_bpp == 8)
1681 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1683 fix->visual = FB_VISUAL_DIRECTCOLOR;
1686 if(XGIfb_ypan) fix->ypanstep = 1;
1689 fix->line_length = xgi_video_info.video_linelength;
1690 fix->mmio_start = xgi_video_info.mmio_base;
1691 fix->mmio_len = XGIfb_mmio_size;
1692 if(xgi_video_info.chip >= XG40)
1693 fix->accel = FB_ACCEL_XGI_XABRE;
1695 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1698 DEBUGPRN("end of get_fix");
1703 static struct fb_ops XGIfb_ops = {
1704 .owner = THIS_MODULE,
1705 .fb_open = XGIfb_open,
1706 .fb_release = XGIfb_release,
1707 .fb_check_var = XGIfb_check_var,
1708 .fb_set_par = XGIfb_set_par,
1709 .fb_setcolreg = XGIfb_setcolreg,
1711 .fb_pan_display = XGIfb_pan_display,
1713 .fb_blank = XGIfb_blank,
1714 .fb_fillrect = fbcon_XGI_fillrect,
1715 .fb_copyarea = fbcon_XGI_copyarea,
1716 .fb_imageblit = cfb_imageblit,
1717 .fb_sync = fbcon_XGI_sync,
1718 .fb_ioctl = XGIfb_ioctl,
1719 // .fb_mmap = XGIfb_mmap,
1722 /* ---------------- Chip generation dependent routines ---------------- */
1725 /* for XGI 315/550/650/740/330 */
1727 static int XGIfb_get_dram_size(void)
1733 /* xorg driver sets 32MB * 1 channel */
1734 if (xgi_video_info.chip == XG27)
1735 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1737 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1738 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1739 case XGI_DRAM_SIZE_1MB:
1740 xgi_video_info.video_size = 0x100000;
1742 case XGI_DRAM_SIZE_2MB:
1743 xgi_video_info.video_size = 0x200000;
1745 case XGI_DRAM_SIZE_4MB:
1746 xgi_video_info.video_size = 0x400000;
1748 case XGI_DRAM_SIZE_8MB:
1749 xgi_video_info.video_size = 0x800000;
1751 case XGI_DRAM_SIZE_16MB:
1752 xgi_video_info.video_size = 0x1000000;
1754 case XGI_DRAM_SIZE_32MB:
1755 xgi_video_info.video_size = 0x2000000;
1757 case XGI_DRAM_SIZE_64MB:
1758 xgi_video_info.video_size = 0x4000000;
1760 case XGI_DRAM_SIZE_128MB:
1761 xgi_video_info.video_size = 0x8000000;
1763 case XGI_DRAM_SIZE_256MB:
1764 xgi_video_info.video_size = 0x10000000;
1770 tmp = (reg & 0x0c) >> 2;
1771 switch(xgi_video_info.chip)
1812 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1813 //PLiad fixed for benchmarking and fb set
1814 //xgi_video_info.video_size = 0x200000;//1024x768x16
1815 //xgi_video_info.video_size = 0x1000000;//benchmark
1817 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1822 static void XGIfb_detect_VB(void)
1826 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1828 switch(xgi_video_info.hasVB) {
1829 case HASVB_LVDS_CHRONTEL:
1830 case HASVB_CHRONTEL:
1834 // XGI_Sense30x(); //Yi-Lin TV Sense?
1838 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1840 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1849 if (XGIfb_crt2type != -1)
1850 /* TW: Override with option */
1851 xgi_video_info.disp_state = XGIfb_crt2type;
1852 else if (cr32 & XGI_VB_TV)
1853 xgi_video_info.disp_state = DISPTYPE_TV;
1854 else if (cr32 & XGI_VB_LCD)
1855 xgi_video_info.disp_state = DISPTYPE_LCD;
1856 else if (cr32 & XGI_VB_CRT2)
1857 xgi_video_info.disp_state = DISPTYPE_CRT2;
1859 xgi_video_info.disp_state = 0;
1861 if(XGIfb_tvplug != -1)
1862 /* PR/TW: Override with option */
1863 xgi_video_info.TV_plug = XGIfb_tvplug;
1864 else if (cr32 & XGI_VB_HIVISION) {
1865 xgi_video_info.TV_type = TVMODE_HIVISION;
1866 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1868 else if (cr32 & XGI_VB_SVIDEO)
1869 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1870 else if (cr32 & XGI_VB_COMPOSITE)
1871 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1872 else if (cr32 & XGI_VB_SCART)
1873 xgi_video_info.TV_plug = TVPLUG_SCART;
1875 if(xgi_video_info.TV_type == 0) {
1876 /* TW: PAL/NTSC changed for 650 */
1877 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1879 inXGIIDXREG(XGICR, 0x38, temp);
1881 xgi_video_info.TV_type = TVMODE_PAL;
1883 xgi_video_info.TV_type = TVMODE_NTSC;
1887 inXGIIDXREG(XGICR, 0x79, temp);
1889 xgi_video_info.TV_type = TVMODE_PAL;
1891 xgi_video_info.TV_type = TVMODE_NTSC;
1895 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1896 if (XGIfb_forcecrt1 != -1) {
1897 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1898 else XGIfb_crt1off = 1;
1902 static void XGIfb_get_VB_type(void)
1906 if (!XGIfb_has_VB()) {
1907 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1908 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1909 case XGI310_EXTERNAL_CHIP_LVDS:
1910 xgi_video_info.hasVB = HASVB_LVDS;
1912 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1913 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1922 static int XGIfb_has_VB(void)
1926 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1927 switch (vb_chipid) {
1929 xgi_video_info.hasVB = HASVB_301;
1932 xgi_video_info.hasVB = HASVB_302;
1935 xgi_video_info.hasVB = HASVB_NONE;
1943 /* ------------------ Sensing routines ------------------ */
1945 /* TW: Determine and detect attached devices on XGI30x */
1947 XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1951 outXGIIDXREG(XGIPART4,0x11,tempbl);
1952 temp = tempbh | tempcl;
1953 setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
1954 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
1956 inXGIIDXREG(XGIPART4,0x03,temp);
1966 u8 testsvhs_tempbl, testsvhs_tempbh;
1967 u8 testsvhs_tempcl, testsvhs_tempch;
1968 u8 testcvbs_tempbl, testcvbs_tempbh;
1969 u8 testcvbs_tempcl, testcvbs_tempch;
1970 u8 testvga2_tempbl, testvga2_tempbh;
1971 u8 testvga2_tempcl, testvga2_tempch;
1974 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
1975 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
1979 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
1980 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
1981 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
1982 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
1983 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
1984 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
1985 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
1986 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
1987 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
1988 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
1989 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
1990 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
1991 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
1994 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
1995 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
1996 inXGIIDXREG(XGIPART4,0x01,myflag);
1998 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
1999 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
2000 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2003 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2004 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2005 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2006 testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2007 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2008 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2010 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2011 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2012 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2016 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2017 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2018 testvga2_tempcl, testvga2_tempch);
2020 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2021 orXGIIDXREG(XGICR, 0x32, 0x10);
2025 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2026 testsvhs_tempcl, testsvhs_tempch);
2028 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2029 /* TW: So we can be sure that there IS a SVHS output */
2030 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2031 orXGIIDXREG(XGICR, 0x32, 0x02);
2035 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2036 testcvbs_tempcl, testcvbs_tempch);
2038 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2039 /* TW: So we can be sure that there IS a CVBS output */
2040 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2041 orXGIIDXREG(XGICR, 0x32, 0x01);
2044 XGIDoSense(0, 0, 0, 0);
2046 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2051 /* ------------------------ Heap routines -------------------------- */
2053 static int XGIfb_heap_init(void)
2058 int agp_enabled = 1;
2060 unsigned long *cmdq_baseport = 0;
2061 unsigned long *read_port = 0;
2062 unsigned long *write_port = 0;
2063 XGI_CMDTYPE cmd_type;
2065 struct agp_kern_info *agp_info;
2066 struct agp_memory *agp;
2070 /* TW: The heap start is either set manually using the "mem" parameter, or
2071 * defaults as follows:
2072 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2073 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2074 * -) If 4MB or less is available, let it start at 4MB.
2075 * This is for avoiding a clash with X driver which uses the beginning
2076 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2078 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2079 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2081 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2082 if (xgi_video_info.video_size > 0x1000000) {
2083 xgi_video_info.heapstart = 0xD00000;
2084 } else if (xgi_video_info.video_size > 0x800000) {
2085 xgi_video_info.heapstart = 0x800000;
2087 xgi_video_info.heapstart = 0x400000;
2090 xgi_video_info.heapstart = XGIfb_mem * 1024;
2093 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2094 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2095 (int)(xgi_video_info.heapstart / 1024));
2097 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2098 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2102 /* TW: Now initialize the 310 series' command queue mode.
2103 * On 310/325, there are three queue modes available which
2104 * are chosen by setting bits 7:5 in SR26:
2105 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2106 * track of the queue, the FIFO, command parsing and so
2107 * on. This is the one comparable to the 300 series.
2108 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2109 * have to do queue management himself. Register 0x85c4 will
2110 * hold the location of the next free queue slot, 0x85c8
2111 * is the "queue read pointer" whose way of working is
2112 * unknown to me. Anyway, this mode would require a
2113 * translation of the MMIO commands to some kind of
2114 * accelerator assembly and writing these commands
2115 * to the memory location pointed to by 0x85c4.
2116 * We will not use this, as nobody knows how this
2117 * "assembly" works, and as it would require a complete
2118 * re-write of the accelerator code.
2119 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2120 * queue in AGP memory space.
2122 * SR26 bit 4 is called "Bypass H/W queue".
2123 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2124 * SR26 bit 0 resets the queue
2125 * Size of queue memory is encoded in bits 3:2 like this:
2130 * The queue location is to be written to 0x85C0.
2133 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2134 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2135 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2137 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2139 agp_size = COMMAND_QUEUE_AREA_SIZE;
2142 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2143 agp_info = vmalloc(sizeof(*agp_info));
2144 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2145 agp_copy_info(agp_info);
2147 agp_backend_acquire();
2149 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2152 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2155 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2156 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2157 /* TODO: Free AGP memory here */
2168 /* TW: Now select the queue mode */
2170 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2171 cmd_type = AGP_CMD_QUEUE;
2172 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2173 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2174 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2175 cmd_type = VM_CMD_QUEUE;
2176 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2178 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2179 cmd_type = MMIO_CMD;
2184 temp = XGI_CMD_QUEUE_SIZE_512k;
2187 temp = XGI_CMD_QUEUE_SIZE_1M;
2190 temp = XGI_CMD_QUEUE_SIZE_2M;
2193 temp = XGI_CMD_QUEUE_SIZE_4M;
2200 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2201 agp_info->aper_base, agp->physical, agp_size/1024);
2203 agp_phys = agp_info->aper_base + agp->physical;
2205 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2206 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2208 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2210 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2212 *write_port = *read_port;
2214 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2215 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2217 *cmdq_baseport = agp_phys;
2219 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2224 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2225 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2227 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2229 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2231 *write_port = *read_port;
2233 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2234 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2236 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2238 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2240 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2241 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2246 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2247 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2248 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2249 * enough. Reserve memory in any way.
2251 // FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2252 // FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2254 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2255 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2257 // FIXME *write_port = *read_port;
2259 // FIXME /* TW: Set Auto_Correction bit */
2260 // FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2261 // FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2263 // FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2265 // FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2267 // FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2268 // FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2275 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2276 top of the videoRAM, right below the TB memory area (if used). */
2277 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2278 XGIfb_heap_end -= XGIfb_hwcursor_size;
2279 XGIfb_heap_size -= XGIfb_hwcursor_size;
2280 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2282 XGIfb_caps |= HW_CURSOR_CAP;
2284 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2285 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2288 XGIfb_heap.poha_chain = NULL;
2289 XGIfb_heap.poh_freelist = NULL;
2291 poh = XGIfb_poh_new_node();
2293 if(poh == NULL) return 1;
2295 poh->poh_next = &XGIfb_heap.oh_free;
2296 poh->poh_prev = &XGIfb_heap.oh_free;
2297 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2298 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2300 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2301 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2302 (unsigned int) poh->size / 1024);
2304 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2305 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2307 XGIfb_heap.oh_free.poh_next = poh;
2308 XGIfb_heap.oh_free.poh_prev = poh;
2309 XGIfb_heap.oh_free.size = 0;
2310 XGIfb_heap.max_freesize = poh->size;
2312 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2313 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2314 XGIfb_heap.oh_used.size = SENTINEL;
2319 static XGI_OH *XGIfb_poh_new_node(void)
2326 if (XGIfb_heap.poh_freelist == NULL) {
2327 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2328 if(!poha) return NULL;
2330 poha->poha_next = XGIfb_heap.poha_chain;
2331 XGIfb_heap.poha_chain = poha;
2333 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2335 poh = &poha->aoh[0];
2336 for (i = cOhs - 1; i != 0; i--) {
2337 poh->poh_next = poh + 1;
2341 poh->poh_next = NULL;
2342 XGIfb_heap.poh_freelist = &poha->aoh[0];
2345 poh = XGIfb_heap.poh_freelist;
2346 XGIfb_heap.poh_freelist = poh->poh_next;
2351 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2357 if (size > XGIfb_heap.max_freesize) {
2358 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2359 (unsigned int) size / 1024);
2363 pohThis = XGIfb_heap.oh_free.poh_next;
2365 while (pohThis != &XGIfb_heap.oh_free) {
2366 if (size <= pohThis->size) {
2370 pohThis = pohThis->poh_next;
2374 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2375 (unsigned int) size / 1024);
2379 if (size == pohThis->size) {
2381 XGIfb_delete_node(pohThis);
2383 pohRoot = XGIfb_poh_new_node();
2385 if (pohRoot == NULL) {
2389 pohRoot->offset = pohThis->offset;
2390 pohRoot->size = size;
2392 pohThis->offset += size;
2393 pohThis->size -= size;
2396 XGIfb_heap.max_freesize -= size;
2398 pohThis = &XGIfb_heap.oh_used;
2399 XGIfb_insert_node(pohThis, pohRoot);
2404 static void XGIfb_delete_node(XGI_OH *poh)
2409 poh_prev = poh->poh_prev;
2410 poh_next = poh->poh_next;
2412 poh_prev->poh_next = poh_next;
2413 poh_next->poh_prev = poh_prev;
2417 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2421 pohTemp = pohList->poh_next;
2423 pohList->poh_next = poh;
2424 pohTemp->poh_prev = poh;
2426 poh->poh_prev = pohList;
2427 poh->poh_next = pohTemp;
2430 static XGI_OH *XGIfb_poh_free(unsigned long base)
2436 unsigned long ulUpper;
2437 unsigned long ulLower;
2440 poh_freed = XGIfb_heap.oh_used.poh_next;
2442 while(poh_freed != &XGIfb_heap.oh_used) {
2443 if(poh_freed->offset == base) {
2448 poh_freed = poh_freed->poh_next;
2451 if (!foundNode) return (NULL);
2453 XGIfb_heap.max_freesize += poh_freed->size;
2455 poh_prev = poh_next = NULL;
2456 ulUpper = poh_freed->offset + poh_freed->size;
2457 ulLower = poh_freed->offset;
2459 pohThis = XGIfb_heap.oh_free.poh_next;
2461 while (pohThis != &XGIfb_heap.oh_free) {
2462 if (pohThis->offset == ulUpper) {
2465 else if ((pohThis->offset + pohThis->size) ==
2469 pohThis = pohThis->poh_next;
2472 XGIfb_delete_node(poh_freed);
2474 if (poh_prev && poh_next) {
2475 poh_prev->size += (poh_freed->size + poh_next->size);
2476 XGIfb_delete_node(poh_next);
2477 XGIfb_free_node(poh_freed);
2478 XGIfb_free_node(poh_next);
2483 poh_prev->size += poh_freed->size;
2484 XGIfb_free_node(poh_freed);
2489 poh_next->size += poh_freed->size;
2490 poh_next->offset = poh_freed->offset;
2491 XGIfb_free_node(poh_freed);
2495 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2500 static void XGIfb_free_node(XGI_OH *poh)
2502 if(poh == NULL) return;
2504 poh->poh_next = XGIfb_heap.poh_freelist;
2505 XGIfb_heap.poh_freelist = poh;
2509 void XGI_malloc(struct XGI_memreq *req)
2513 poh = XGIfb_poh_allocate(req->size);
2518 DPRINTK("XGIfb: Video RAM allocation failed\n");
2520 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2521 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2523 req->offset = poh->offset;
2524 req->size = poh->size;
2529 void XGI_free(unsigned long base)
2533 poh = XGIfb_poh_free(base);
2536 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2537 (unsigned int) base);
2541 /* --------------------- SetMode routines ------------------------- */
2543 static void XGIfb_pre_setmode(void)
2545 u8 cr30 = 0, cr31 = 0;
2547 inXGIIDXREG(XGICR, 0x31, cr31);
2550 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2552 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2553 cr31 |= XGI_DRIVER_MODE;
2556 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2557 cr31 |= XGI_DRIVER_MODE;
2560 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2561 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2562 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2563 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2564 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2565 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2566 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2567 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2568 cr31 |= XGI_DRIVER_MODE;
2570 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2575 default: /* disable CRT2 */
2577 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2580 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2581 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2582 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2584 if(xgi_video_info.accel) XGIfb_syncaccel();
2589 static void XGIfb_post_setmode(void)
2592 unsigned char doit = 1;
2593 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2594 outXGIIDXREG(XGICR,0x13,0x00);
2595 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2597 if (xgi_video_info.video_bpp == 8) {
2598 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2599 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2602 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2603 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2608 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2609 if(xgi_video_info.hasVB != HASVB_NONE) {
2610 inXGIIDXREG(XGIPART1, 0x00, reg);
2613 if ((reg & 0x50) == 0x10)
2620 inXGIIDXREG(XGICR, 0x17, reg);
2621 if ((XGIfb_crt1off) && (doit))
2625 outXGIIDXREG(XGICR, 0x17, reg);
2627 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2629 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2631 inXGIIDXREG(XGIPART4, 0x01, reg);
2633 if(reg < 0xB0) { /* Set filter for XGI301 */
2635 switch (xgi_video_info.video_width) {
2637 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2640 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2643 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2646 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2653 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2655 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2657 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2659 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2661 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2663 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2665 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2667 switch (xgi_video_info.video_width) {
2669 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2670 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2671 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2672 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2675 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2676 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2677 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2678 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2681 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2682 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2683 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2684 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2689 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2691 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2693 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2695 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2697 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2699 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2701 switch (xgi_video_info.video_width) {
2703 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2704 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2705 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2706 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2709 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2710 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2711 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2712 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2715 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2716 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2717 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2718 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2724 if ((filter >= 0) && (filter <=7)) {
2725 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2726 XGI_TV_filter[filter_tb].filter[filter][0],
2727 XGI_TV_filter[filter_tb].filter[filter][1],
2728 XGI_TV_filter[filter_tb].filter[filter][2],
2729 XGI_TV_filter[filter_tb].filter[filter][3]
2731 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2732 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2733 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2734 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2744 XGIINITSTATIC int __init XGIfb_setup(char *options)
2750 xgi_video_info.refresh_rate = 0;
2752 printk(KERN_INFO "XGIfb: Options %s\n", options);
2754 if (!options || !*options)
2757 while((this_opt = strsep(&options, ",")) != NULL) {
2759 if (!*this_opt) continue;
2761 if (!strncmp(this_opt, "mode:", 5)) {
2762 XGIfb_search_mode(this_opt + 5);
2763 } else if (!strncmp(this_opt, "vesa:", 5)) {
2764 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2765 } else 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, "vrate:", 6)) {
2770 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2771 } else if (!strncmp(this_opt, "rate:", 5)) {
2772 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2773 } else if (!strncmp(this_opt, "off", 3)) {
2775 } else if (!strncmp(this_opt, "crt1off", 7)) {
2777 } else if (!strncmp(this_opt, "filter:", 7)) {
2778 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2779 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2780 XGIfb_search_crt2type(this_opt + 14);
2781 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2782 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2783 } else if (!strncmp(this_opt, "tvmode:",7)) {
2784 XGIfb_search_tvstd(this_opt + 7);
2785 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2786 XGIfb_search_tvstd(this_opt + 7);
2787 } else if (!strncmp(this_opt, "mem:",4)) {
2788 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2789 } else if (!strncmp(this_opt, "dstn", 4)) {
2791 /* TW: DSTN overrules forcecrt2type */
2792 XGIfb_crt2type = DISPTYPE_LCD;
2793 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2794 XGIfb_search_queuemode(this_opt + 10);
2795 } else if (!strncmp(this_opt, "pdc:", 4)) {
2796 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2797 if(XGIfb_pdc & ~0x3c) {
2798 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2801 } else if (!strncmp(this_opt, "noaccel", 7)) {
2803 } else if (!strncmp(this_opt, "noypan", 6)) {
2805 } else if (!strncmp(this_opt, "userom:", 7)) {
2806 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2807 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2808 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2810 XGIfb_search_mode(this_opt);
2811 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2814 /* TW: Acceleration only with MMIO mode */
2815 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2819 /* TW: Panning only with acceleration */
2820 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2823 printk("\nxgifb: outa xgifb_setup 3450");
2828 static unsigned char VBIOS_BUF[65535];
2830 unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
2833 u32 rom_address = 0;
2836 /* Get the size of the expansion rom */
2837 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2838 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2839 if ((rom_size & 0x01) == 0)
2845 rom_size &= 0xFFFFF800;
2846 rom_size = (~rom_size)+1;
2848 rom_address = pci_resource_start(dev, 0);
2849 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2851 printk("No suitable rom address found\n"); return NULL;
2854 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2857 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2859 /* memcpy(copy_address, rom_address, rom_size); */
2861 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2863 unsigned char *from = (unsigned char *)virt_addr;
2864 unsigned char *to = (unsigned char *)copy_address;
2865 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2868 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2870 printk("Copy is done\n");
2872 return copy_address;
2875 int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2883 XGIfb_registered = 0;
2885 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2886 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2887 if(!fb_info) return -ENOMEM;
2889 xgi_video_info.chip_id = pdev->device;
2890 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2891 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2892 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2893 XGIvga_enabled = reg16 & 0x01;
2895 xgi_video_info.pcibus = pdev->bus->number;
2896 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2897 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2898 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2899 xgi_video_info.subsysdevice = pdev->subsystem_device;
2901 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2902 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2903 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2904 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2905 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2906 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2907 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2908 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2910 if (pci_enable_device(pdev))
2913 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2915 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2916 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2918 if(reg1 != 0xa1) /*I/O error */
2920 printk("\nXGIfb: I/O error!!!");
2924 switch (xgi_video_info.chip_id) {
2925 case PCI_DEVICE_ID_XG_20:
2926 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2927 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2928 if (CR48&GPIOG_READ)
2929 xgi_video_info.chip = XG21;
2931 xgi_video_info.chip = XG20;
2932 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2933 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2935 case PCI_DEVICE_ID_XG_40:
2936 xgi_video_info.chip = XG40;
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_41:
2941 xgi_video_info.chip = XG41;
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_42:
2946 xgi_video_info.chip = XG42;
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_27:
2951 xgi_video_info.chip = XG27;
2952 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2953 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2959 printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
2960 XGIhw_ext.jChipType = xgi_video_info.chip;
2962 switch (xgi_video_info.chip) {
2970 XGIhw_ext.bIntegratedMMEnabled = 1;
2978 XGIhw_ext.pDevice = NULL;
2979 if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
2981 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
2983 if(XGIhw_ext.pjVirtualRomBase)
2984 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
2986 printk(KERN_INFO "XGIfb: Video ROM not found\n");
2988 XGIhw_ext.pjVirtualRomBase = NULL;
2989 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2991 XGIhw_ext.pjCustomizedROMImage = NULL;
2992 XGIhw_ext.bSkipDramSizing = 0;
2993 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2994 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
2995 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
2998 XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
2999 if (XGIhw_ext.pSR == NULL)
3001 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3004 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3006 XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
3007 if (XGIhw_ext.pCR == NULL)
3009 vfree(XGIhw_ext.pSR);
3010 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3013 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3018 if (!XGIvga_enabled)
3020 /* Mapping Max FB Size for 315 Init */
3021 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3022 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3025 printk("XGIfb: XGIInit() ...");
3026 /* XGIInitNewt for LINUXBIOS only */
3027 if(XGIInitNew(&XGIhw_ext))
3037 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3045 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3046 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3049 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3051 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3052 // Set SR13 ,14 temporarily for UDtech
3053 outXGIIDXREG(XGISR, 0x13, 0x45);
3054 outXGIIDXREG(XGISR, 0x14, 0x51);
3060 if (XGIfb_get_dram_size())
3062 vfree(XGIhw_ext.pSR);
3063 vfree(XGIhw_ext.pCR);
3064 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3070 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3072 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3073 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3074 /* Enable 2D accelerator engine */
3075 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3078 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3080 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3081 { printk("unable request memory size %x",xgi_video_info.video_size);
3082 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3083 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3084 vfree(XGIhw_ext.pSR);
3085 vfree(XGIhw_ext.pCR);
3089 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3091 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3092 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3093 vfree(XGIhw_ext.pSR);
3094 vfree(XGIhw_ext.pCR);
3098 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3099 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3100 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3102 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3103 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3105 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3106 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3107 printk("XGIfb: XGIInitNew() ...");
3108 if(XGIInitNew(&XGIhw_ext))
3117 if(XGIfb_heap_init())
3119 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3123 xgi_video_info.mtrr = (unsigned int) 0;
3125 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3127 xgi_video_info.hasVB = HASVB_NONE;
3128 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3129 xgi_video_info.hasVB = HASVB_NONE;
3130 else if(xgi_video_info.chip == XG21) {
3131 inXGIIDXREG(XGICR,0x38,CR38);
3132 if ((CR38&0xE0) == 0xC0) {
3133 xgi_video_info.disp_state = DISPTYPE_LCD;
3134 if (!XGIfb_GetXG21LVDSData()) {
3136 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3137 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3138 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3139 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3144 else if ((CR38&0xE0) == 0x60)
3145 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3147 xgi_video_info.hasVB = HASVB_NONE;
3150 XGIfb_get_VB_type();
3152 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3154 XGIhw_ext.ulExternalChip = 0;
3156 switch (xgi_video_info.hasVB) {
3158 inXGIIDXREG(XGIPART4, 0x01, reg);
3160 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3161 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3162 } else if (reg >= 0xD0) {
3163 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3164 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3166 /* else if (reg >= 0xB0) {
3167 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3168 inXGIIDXREG(XGIPART4,0x23,reg1);
3169 printk("XGIfb: XGI301B bridge detected\n");
3172 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3173 printk("XGIfb: XGI301 bridge detected\n");
3177 inXGIIDXREG(XGIPART4, 0x01, reg);
3179 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3180 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3181 } else if (reg >= 0xD0) {
3182 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3183 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3184 } else if (reg >= 0xB0) {
3185 inXGIIDXREG(XGIPART4,0x23,reg1);
3187 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3190 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3191 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3195 XGIhw_ext.ulExternalChip = 0x1;
3196 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3198 case HASVB_TRUMPION:
3199 XGIhw_ext.ulExternalChip = 0x2;
3200 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3202 case HASVB_CHRONTEL:
3203 XGIhw_ext.ulExternalChip = 0x4;
3204 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3206 case HASVB_LVDS_CHRONTEL:
3207 XGIhw_ext.ulExternalChip = 0x5;
3208 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3211 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3215 if (xgi_video_info.hasVB != HASVB_NONE) {
3219 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3221 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3223 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3225 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3228 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3230 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3232 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3236 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3240 XGIfb_detectedpdc = 0;
3242 XGIfb_detectedlcda = 0xff;
3245 /* TW: Try to find about LCDA */
3247 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3248 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3249 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3252 inXGIIDXREG(XGICR,0x34,tmp);
3255 // Currently on LCDA? (Some BIOSes leave CR38)
3256 inXGIIDXREG(XGICR,0x38,tmp);
3257 if((tmp & 0x03) == 0x03)
3259 /* XGI_Pr.XGI_UseLCDA = 1; */
3262 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3263 inXGIIDXREG(XGICR,0x35,tmp);
3266 /* XGI_Pr.XGI_UseLCDA = 1; */
3269 inXGIIDXREG(XGICR,0x30,tmp);
3272 inXGIIDXREG(XGIPART1,0x13,tmp);
3275 /* XGI_Pr.XGI_UseLCDA = 1; */
3287 if (xgifb_mode_idx >= 0)
3288 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3290 if (xgifb_mode_idx < 0) {
3291 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3293 xgifb_mode_idx = DEFAULT_LCDMODE;
3294 if (xgi_video_info.chip == XG21)
3296 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3300 xgifb_mode_idx = DEFAULT_TVMODE;
3303 xgifb_mode_idx = DEFAULT_MODE;
3308 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3311 if( xgi_video_info.refresh_rate == 0)
3312 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3313 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3315 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3316 xgi_video_info.refresh_rate = 60;
3319 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3320 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3321 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3322 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3323 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3324 switch(xgi_video_info.video_bpp) {
3326 xgi_video_info.DstColor = 0x0000;
3327 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3328 xgi_video_info.video_cmap_len = 256;
3331 xgi_video_info.DstColor = 0x8000;
3332 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3333 xgi_video_info.video_cmap_len = 16;
3336 xgi_video_info.DstColor = 0xC000;
3337 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3338 xgi_video_info.video_cmap_len = 16;
3341 xgi_video_info.video_cmap_len = 16;
3342 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3348 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3349 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3350 xgi_video_info.refresh_rate);
3352 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3353 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3354 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3356 XGIfb_bpp_to_var(&default_var);
3358 default_var.pixclock = (u32) (1000000000 /
3359 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3360 XGIfb_mode_no, XGIfb_rate_idx));
3362 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3363 XGIfb_mode_no, XGIfb_rate_idx,
3364 &default_var.left_margin, &default_var.right_margin,
3365 &default_var.upper_margin, &default_var.lower_margin,
3366 &default_var.hsync_len, &default_var.vsync_len,
3367 &default_var.sync, &default_var.vmode)) {
3369 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3370 default_var.yres <<= 1;
3371 default_var.yres_virtual <<= 1;
3372 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3373 default_var.pixclock >>= 1;
3374 default_var.yres >>= 1;
3375 default_var.yres_virtual >>= 1;
3380 xgi_video_info.accel = 0;
3382 xgi_video_info.accel = -1;
3383 default_var.accel_flags |= FB_ACCELF_TEXT;
3387 fb_info->flags = FBINFO_FLAG_DEFAULT;
3388 fb_info->var = default_var;
3389 fb_info->fix = XGIfb_fix;
3390 fb_info->par = &xgi_video_info;
3391 fb_info->screen_base = xgi_video_info.video_vbase;
3392 fb_info->fbops = &XGIfb_ops;
3393 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3394 fb_info->pseudo_palette = pseudo_palette;
3396 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3400 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3401 (unsigned int) xgi_video_info.video_size,
3402 MTRR_TYPE_WRCOMB, 1);
3403 if(xgi_video_info.mtrr) {
3404 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3408 if(register_framebuffer(fb_info) < 0)
3413 XGIfb_registered = 1;
3415 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
3418 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3419 XGIfb_accel ? "enabled" : "disabled",
3420 XGIfb_ypan ? "ypan" : "redraw");
3422 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3423 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3434 /*****************************************************/
3435 /* PCI DEVICE HANDLING */
3436 /*****************************************************/
3438 static void __devexit xgifb_remove(struct pci_dev *pdev)
3440 /* Unregister the framebuffer */
3441 // if(xgi_video_info.registered) {
3442 unregister_framebuffer(fb_info);
3443 framebuffer_release(fb_info);
3446 pci_set_drvdata(pdev, NULL);
3450 static struct pci_driver xgifb_driver = {
3452 .id_table = xgifb_pci_table,
3453 .probe = xgifb_probe,
3454 .remove = __devexit_p(xgifb_remove)
3457 XGIINITSTATIC int __init xgifb_init(void)
3460 char *option = NULL;
3462 if (fb_get_options("xgifb", &option))
3464 XGIfb_setup(option);
3466 return(pci_register_driver(&xgifb_driver));
3471 module_init(xgifb_init);
3474 /*****************************************************/
3476 /*****************************************************/
3480 static char *mode = NULL;
3481 static int vesa = 0;
3482 static unsigned int rate = 0;
3483 static unsigned int crt1off = 1;
3484 static unsigned int mem = 0;
3485 static char *forcecrt2type = NULL;
3486 static int forcecrt1 = -1;
3487 static int pdc = -1;
3488 static int pdc1 = -1;
3489 static int noaccel = -1;
3490 static int noypan = -1;
3491 static int nomax = -1;
3492 static int userom = -1;
3493 static int useoem = -1;
3494 static char *tvstandard = NULL;
3495 static int nocrt2rate = 0;
3496 static int scalelcd = -1;
3497 static char *specialtiming = NULL;
3498 static int lvdshl = -1;
3499 static int tvxposoffset = 0, tvyposoffset = 0;
3500 #if !defined(__i386__) && !defined(__x86_64__)
3501 static int resetcard = 0;
3502 static int videoram = 0;
3505 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3506 MODULE_LICENSE("GPL");
3507 MODULE_AUTHOR("XGITECH , Others");
3511 module_param(mem, int, 0);
3512 module_param(noaccel, int, 0);
3513 module_param(noypan, int, 0);
3514 module_param(nomax, int, 0);
3515 module_param(userom, int, 0);
3516 module_param(useoem, int, 0);
3517 module_param(mode, charp, 0);
3518 module_param(vesa, int, 0);
3519 module_param(rate, int, 0);
3520 module_param(forcecrt1, int, 0);
3521 module_param(forcecrt2type, charp, 0);
3522 module_param(scalelcd, int, 0);
3523 module_param(pdc, int, 0);
3524 module_param(pdc1, int, 0);
3525 module_param(specialtiming, charp, 0);
3526 module_param(lvdshl, int, 0);
3527 module_param(tvstandard, charp, 0);
3528 module_param(tvxposoffset, int, 0);
3529 module_param(tvyposoffset, int, 0);
3530 module_param(filter, int, 0);
3531 module_param(nocrt2rate, int, 0);
3532 #if !defined(__i386__) && !defined(__x86_64__)
3533 module_param(resetcard, int, 0);
3534 module_param(videoram, int, 0);
3538 MODULE_PARM_DESC(mem,
3539 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3540 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3541 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3542 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3543 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3544 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3545 "for XFree86 4.x/X.org 6.7 and later.\n");
3547 MODULE_PARM_DESC(noaccel,
3548 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3551 MODULE_PARM_DESC(noypan,
3552 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3553 "will be performed by redrawing the screen. (default: 0)\n");
3555 MODULE_PARM_DESC(nomax,
3556 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3557 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3558 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3559 "enable the user to positively specify a virtual Y size of the screen using\n"
3560 "fbset. (default: 0)\n");
3564 MODULE_PARM_DESC(mode,
3565 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3566 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3567 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3568 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3570 MODULE_PARM_DESC(vesa,
3571 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3572 "0x117 (default: 0x0103)\n");
3575 MODULE_PARM_DESC(rate,
3576 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3577 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3578 "will be ignored (default: 60)\n");
3580 MODULE_PARM_DESC(forcecrt1,
3581 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3582 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3583 "0=CRT1 OFF) (default: [autodetected])\n");
3585 MODULE_PARM_DESC(forcecrt2type,
3586 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3587 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3588 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3589 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3590 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3591 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3592 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3593 "depends on the very hardware in use. (default: [autodetected])\n");
3595 MODULE_PARM_DESC(scalelcd,
3596 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3597 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3598 "show black bars around the image, TMDS panels will probably do the scaling\n"
3599 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3601 MODULE_PARM_DESC(pdc,
3602 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3603 "should detect this correctly in most cases; however, sometimes this is not\n"
3604 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3605 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3606 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3607 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3609 MODULE_PARM_DESC(pdc1,
3610 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3611 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3612 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3613 "implemented yet.\n");
3615 MODULE_PARM_DESC(specialtiming,
3616 "\nPlease refer to documentation for more information on this option.\n");
3618 MODULE_PARM_DESC(lvdshl,
3619 "\nPlease refer to documentation for more information on this option.\n");
3621 MODULE_PARM_DESC(tvstandard,
3622 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3623 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3625 MODULE_PARM_DESC(tvxposoffset,
3626 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3629 MODULE_PARM_DESC(tvyposoffset,
3630 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3633 MODULE_PARM_DESC(filter,
3634 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3635 "(Possible values 0-7, default: [no filter])\n");
3637 MODULE_PARM_DESC(nocrt2rate,
3638 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3639 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3644 int __init xgifb_init_module(void)
3646 printk("\nXGIfb_init_module");
3648 XGIfb_search_mode(mode);
3649 else if (vesa != -1)
3650 XGIfb_search_vesamode(vesa);
3652 return(xgifb_init());
3655 static void __exit xgifb_remove_module(void)
3657 pci_unregister_driver(&xgifb_driver);
3658 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3661 module_init(xgifb_init_module);
3662 module_exit(xgifb_remove_module);
3664 #endif /* /MODULE */
3666 EXPORT_SYMBOL(XGI_malloc);
3667 EXPORT_SYMBOL(XGI_free);