2 * XG20, XG21, XG40, XG42 frame buffer device
3 * for Linux kernels 2.5.x, 2.6.x
4 * Base on TW's sis fbdev code.
7 //#include <linux/config.h>
8 #include <linux/version.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
20 #include <linux/console.h>
21 #include <linux/selection.h>
22 #include <linux/ioport.h>
23 #include <linux/init.h>
24 #include <linux/pci.h>
25 #include <linux/vmalloc.h>
26 #include <linux/vt_kern.h>
27 #include <linux/capability.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
48 #define Index_CR_GPIO_Reg1 0x48
49 #define Index_CR_GPIO_Reg2 0x49
50 #define Index_CR_GPIO_Reg3 0x4a
52 #define GPIOG_EN (1<<6)
53 #define GPIOG_WRITE (1<<6)
54 #define GPIOG_READ (1<<1)
55 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
57 /* -------------------- Macro definitions ---------------------------- */
62 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
64 #define DPRINTK(fmt, args...)
68 static void dumpVGAReg(void)
72 outXGIIDXREG(XGISR, 0x05, 0x86);
74 outXGIIDXREG(XGISR, 0x08, 0x4f);
75 outXGIIDXREG(XGISR, 0x0f, 0x20);
76 outXGIIDXREG(XGISR, 0x11, 0x4f);
77 outXGIIDXREG(XGISR, 0x13, 0x45);
78 outXGIIDXREG(XGISR, 0x14, 0x51);
79 outXGIIDXREG(XGISR, 0x1e, 0x41);
80 outXGIIDXREG(XGISR, 0x1f, 0x0);
81 outXGIIDXREG(XGISR, 0x20, 0xa1);
82 outXGIIDXREG(XGISR, 0x22, 0xfb);
83 outXGIIDXREG(XGISR, 0x26, 0x22);
84 outXGIIDXREG(XGISR, 0x3e, 0x07);
87 //outXGIIDXREG(XGICR, 0x19, 0x00);
88 //outXGIIDXREG(XGICR, 0x1a, 0x3C);
89 //outXGIIDXREG(XGICR, 0x22, 0xff);
90 //outXGIIDXREG(XGICR, 0x3D, 0x10);
92 //outXGIIDXREG(XGICR, 0x4a, 0xf3);
94 //outXGIIDXREG(XGICR, 0x57, 0x0);
95 //outXGIIDXREG(XGICR, 0x7a, 0x2c);
97 //outXGIIDXREG(XGICR, 0x82, 0xcc);
98 //outXGIIDXREG(XGICR, 0x8c, 0x0);
100 outXGIIDXREG(XGICR, 0x99, 0x1);
101 outXGIIDXREG(XGICR, 0x41, 0x40);
104 for(i=0; i < 0x4f; i++)
106 inXGIIDXREG(XGISR, i, reg);
107 printk("\no 3c4 %x",i);
108 printk("\ni 3c5 => %x",reg);
111 for(i=0; i < 0xF0; i++)
113 inXGIIDXREG(XGICR, i, reg);
114 printk("\no 3d4 %x",i);
115 printk("\ni 3d5 => %x",reg);
119 outXGIIDXREG(XGIPART1,0x2F,1);
120 for(i=1; i < 0x50; i++)
122 inXGIIDXREG(XGIPART1, i, reg);
123 printk("\no d004 %x",i);
124 printk("\ni d005 => %x",reg);
127 for(i=0; i < 0x50; i++)
129 inXGIIDXREG(XGIPART2, i, reg);
130 printk("\no d010 %x",i);
131 printk("\ni d011 => %x",reg);
133 for(i=0; i < 0x50; i++)
135 inXGIIDXREG(XGIPART3, i, reg);
136 printk("\no d012 %x",i);
137 printk("\ni d013 => %x",reg);
139 for(i=0; i < 0x50; i++)
141 inXGIIDXREG(XGIPART4, i, reg);
142 printk("\no d014 %x",i);
143 printk("\ni d015 => %x",reg);
148 static inline void dumpVGAReg(void) {}
151 /* data for XGI components */
152 struct video_info xgi_video_info;
158 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
162 /* --------------- Hardware Access Routines -------------------------- */
165 XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
166 unsigned char modeno, unsigned char rateindex)
168 USHORT ModeNo = modeno;
169 USHORT ModeIdIndex = 0, ClockIndex = 0;
170 USHORT RefreshRateTableIndex = 0;
174 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
175 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
177 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
180 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
182 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
186 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
187 RefreshRateTableIndex += (rateindex - 1);
190 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
191 if(HwDeviceExtension->jChipType < XGI_315H) {
194 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
200 XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
201 unsigned char modeno, unsigned char rateindex,
202 u32 *left_margin, u32 *right_margin,
203 u32 *upper_margin, u32 *lower_margin,
204 u32 *hsync_len, u32 *vsync_len,
205 u32 *sync, u32 *vmode)
207 USHORT ModeNo = modeno;
208 USHORT ModeIdIndex = 0, index = 0;
209 USHORT RefreshRateTableIndex = 0;
211 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
212 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
213 unsigned char sr_data, cr_data, cr_data2;
214 unsigned long cr_data3;
215 int A, B, C, D, E, F, temp, j;
216 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
217 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
218 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
220 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
223 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
224 RefreshRateTableIndex += (rateindex - 1);
226 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
228 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
230 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
232 /* Horizontal total */
233 HT = (cr_data & 0xff) |
234 ((unsigned short) (sr_data & 0x03) << 8);
237 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
239 Horizontal display enable end
240 HDE = (cr_data & 0xff) |
241 ((unsigned short) (sr_data & 0x0C) << 6);*/
242 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
245 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
247 /* Horizontal retrace (=sync) start */
248 HRS = (cr_data & 0xff) |
249 ((unsigned short) (sr_data & 0xC0) << 2);
252 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
254 /* Horizontal blank start */
255 HBS = (cr_data & 0xff) |
256 ((unsigned short) (sr_data & 0x30) << 4);
258 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
260 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
262 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
264 /* Horizontal blank end */
265 HBE = (cr_data & 0x1f) |
266 ((unsigned short) (cr_data2 & 0x80) >> 2) |
267 ((unsigned short) (sr_data & 0x03) << 6);
269 /* Horizontal retrace (=sync) end */
270 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
272 temp = HBE - ((E - 1) & 255);
273 B = (temp > 0) ? temp : (temp + 256);
275 temp = HRE - ((E + F + 3) & 63);
276 C = (temp > 0) ? temp : (temp + 64);
280 *left_margin = D * 8;
281 *right_margin = F * 8;
284 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
286 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
288 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
291 VT = (cr_data & 0xFF) |
292 ((unsigned short) (cr_data2 & 0x01) << 8) |
293 ((unsigned short)(cr_data2 & 0x20) << 4) |
294 ((unsigned short) (sr_data & 0x01) << 10);
297 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
299 /* Vertical display enable end */
300 /* VDE = (cr_data & 0xff) |
301 ((unsigned short) (cr_data2 & 0x02) << 7) |
302 ((unsigned short) (cr_data2 & 0x40) << 3) |
303 ((unsigned short) (sr_data & 0x02) << 9); */
304 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1;
307 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
309 /* Vertical retrace (=sync) start */
310 VRS = (cr_data & 0xff) |
311 ((unsigned short) (cr_data2 & 0x04) << 6) |
312 ((unsigned short) (cr_data2 & 0x80) << 2) |
313 ((unsigned short) (sr_data & 0x08) << 7);
316 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
318 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
320 /* Vertical blank start */
321 VBS = (cr_data & 0xff) |
322 ((unsigned short) (cr_data2 & 0x08) << 5) |
323 ((unsigned short) (cr_data3 & 0x20) << 4) |
324 ((unsigned short) (sr_data & 0x04) << 8);
326 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
328 /* Vertical blank end */
329 VBE = (cr_data & 0xff) |
330 ((unsigned short) (sr_data & 0x10) << 4);
331 temp = VBE - ((E - 1) & 511);
332 B = (temp > 0) ? temp : (temp + 512);
334 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
336 /* Vertical retrace (=sync) end */
337 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
338 temp = VRE - ((E + F - 1) & 31);
339 C = (temp > 0) ? temp : (temp + 32);
347 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
348 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
350 *sync |= FB_SYNC_VERT_HIGH_ACT;
352 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
353 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
355 *sync |= FB_SYNC_HOR_HIGH_ACT;
357 *vmode = FB_VMODE_NONINTERLACED;
358 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
359 *vmode = FB_VMODE_INTERLACED;
362 while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
363 if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
364 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
365 if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
366 *vmode = FB_VMODE_DOUBLE;
374 #if 0 /* That's bullshit, only the resolution needs to be shifted */
375 if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
379 } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
392 void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
394 XGI_Pr->RelIO = BaseAddr;
395 XGI_Pr->P3c4 = BaseAddr + 0x14;
396 XGI_Pr->P3d4 = BaseAddr + 0x24;
397 XGI_Pr->P3c0 = BaseAddr + 0x10;
398 XGI_Pr->P3ce = BaseAddr + 0x1e;
399 XGI_Pr->P3c2 = BaseAddr + 0x12;
400 XGI_Pr->P3ca = BaseAddr + 0x1a;
401 XGI_Pr->P3c6 = BaseAddr + 0x16;
402 XGI_Pr->P3c7 = BaseAddr + 0x17;
403 XGI_Pr->P3c8 = BaseAddr + 0x18;
404 XGI_Pr->P3c9 = BaseAddr + 0x19;
405 XGI_Pr->P3da = BaseAddr + 0x2A;
406 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
407 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
408 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
409 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
410 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
415 void XGIfb_set_reg4(u16 port, unsigned long data)
417 outl((u32) (data & 0xffffffff), port);
420 u32 XGIfb_get_reg3(u16 port)
428 /* ------------ Interface for init & mode switching code ------------- */
431 XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
432 unsigned long offset, unsigned long set, unsigned long *value)
434 static struct pci_dev *pdev = NULL;
435 static unsigned char init = 0, valid_pdev = 0;
438 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
440 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
444 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
452 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
453 xgi_video_info.chip_id);
458 pci_read_config_dword(pdev, offset, (u32 *)value);
460 pci_write_config_dword(pdev, offset, (u32)(*value));
465 /*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
466 unsigned long offset, unsigned long set, unsigned long *value)
468 static struct pci_dev *pdev = NULL;
469 static unsigned char init = 0, valid_pdev = 0;
474 switch (xgi_video_info.chip) {
476 nbridge_id = PCI_DEVICE_ID_XG_540;
479 nbridge_id = PCI_DEVICE_ID_XG_630;
482 nbridge_id = PCI_DEVICE_ID_XG_730;
485 nbridge_id = PCI_DEVICE_ID_XG_550;
488 nbridge_id = PCI_DEVICE_ID_XG_650;
491 nbridge_id = PCI_DEVICE_ID_XG_740;
498 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
504 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
510 pci_read_config_dword(pdev, offset, (u32 *)value);
512 pci_write_config_dword(pdev, offset, (u32)(*value));
517 /* ------------------ Internal helper routines ----------------- */
519 static void XGIfb_search_mode(const char *name)
524 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
525 xgifb_mode_idx = DEFAULT_MODE;
526 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
528 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
534 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
535 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
536 xgifb_mode_idx = DEFAULT_MODE;
537 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
539 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
544 while(XGIbios_mode[i].mode_no != 0) {
545 l = min(strlen(name), strlen(XGIbios_mode[i].name));
546 if (!strncmp(name, XGIbios_mode[i].name, l)) {
553 if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
556 static void XGIfb_search_vesamode(unsigned int vesamode)
562 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
563 xgifb_mode_idx = DEFAULT_MODE;
564 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
566 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
571 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
573 while(XGIbios_mode[i].mode_no != 0) {
574 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
575 (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
582 if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
585 int XGIfb_GetXG21LVDSData(void)
588 unsigned char *pData;
591 inXGIIDXREG(XGISR,0x1e,tmp);
592 outXGIIDXREG(XGISR, 0x1e, tmp|4);
594 pData = xgi_video_info.mmio_vbase+0x20000;
595 if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
597 i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
606 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
607 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
608 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
609 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
610 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
611 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
612 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
613 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
614 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
615 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
616 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
617 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
618 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
619 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
620 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
621 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
625 } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
631 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
635 int XGIfb_mode_idx = 0;
638 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
639 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
641 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
642 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
643 (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
645 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
654 return (XGIfb_mode_idx);
658 static int XGIfb_validate_mode(int myindex)
662 if (xgi_video_info.chip == XG21)
664 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
666 xres = XGI21_LCDCapList[0].LVDSHDE;
667 yres = XGI21_LCDCapList[0].LVDSVDE;
668 if(XGIbios_mode[myindex].xres > xres)
670 if(XGIbios_mode[myindex].yres > yres)
672 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
674 if (XGIbios_mode[myindex].bpp > 8)
683 /* FIXME: for now, all is valid on XG27 */
684 if (xgi_video_info.chip == XG27)
687 if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
690 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
692 switch (XGIhw_ext.ulCRT2LCDType) {
694 xres = 640; yres = 480; break;
696 xres = 800; yres = 600; break;
698 xres = 1024; yres = 600; break;
700 xres = 1024; yres = 768; break;
702 xres = 1152; yres = 768; break;
704 xres = 1280; yres = 960; break;
706 xres = 1280; yres = 768; break;
708 xres = 1280; yres = 1024; break;
710 xres = 1400; yres = 1050; break;
712 xres = 1600; yres = 1200; break;
713 // case LCD_320x480: // TW: FSTN
714 // xres = 320; yres = 480; break;
716 xres = 0; yres = 0; break;
718 if(XGIbios_mode[myindex].xres > xres) {
721 if(XGIbios_mode[myindex].yres > yres) {
724 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
725 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
727 switch (XGIbios_mode[myindex].xres) {
729 if(XGIbios_mode[myindex].yres != 512) return -1;
730 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
733 if((XGIbios_mode[myindex].yres != 400) &&
734 (XGIbios_mode[myindex].yres != 480))
738 if(XGIbios_mode[myindex].yres != 600) return -1;
741 if((XGIbios_mode[myindex].yres != 600) &&
742 (XGIbios_mode[myindex].yres != 768))
744 if((XGIbios_mode[myindex].yres == 600) &&
745 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
749 if((XGIbios_mode[myindex].yres) != 768) return -1;
750 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
753 if((XGIbios_mode[myindex].yres != 768) &&
754 (XGIbios_mode[myindex].yres != 1024))
756 if((XGIbios_mode[myindex].yres == 768) &&
757 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
761 if(XGIbios_mode[myindex].yres != 1050) return -1;
764 if(XGIbios_mode[myindex].yres != 1200) return -1;
770 switch (XGIbios_mode[myindex].xres) {
772 if(XGIbios_mode[myindex].yres != 512) return -1;
775 if((XGIbios_mode[myindex].yres != 400) &&
776 (XGIbios_mode[myindex].yres != 480))
780 if(XGIbios_mode[myindex].yres != 600) return -1;
783 if(XGIbios_mode[myindex].yres != 768) return -1;
786 if((XGIbios_mode[myindex].yres != 960) &&
787 (XGIbios_mode[myindex].yres != 1024))
789 if(XGIbios_mode[myindex].yres == 960) {
790 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
795 if(XGIbios_mode[myindex].yres != 1050) return -1;
798 if(XGIbios_mode[myindex].yres != 1200) return -1;
806 switch (XGIbios_mode[myindex].xres) {
812 if (xgi_video_info.TV_type == TVMODE_NTSC) {
813 if (XGIbios_mode[myindex].yres != 480) {
816 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
817 if (XGIbios_mode[myindex].yres != 576) {
821 // TW: LVDS/CHRONTEL does not support 720
822 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
823 xgi_video_info.hasVB == HASVB_CHRONTEL) {
828 if (xgi_video_info.TV_type == TVMODE_NTSC) {
829 if(XGIbios_mode[myindex].bpp == 32) {
833 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
834 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
835 xgi_video_info.hasVB == HASVB_CHRONTEL) {
836 if(xgi_video_info.chip < XGI_315H) {
846 if(XGIbios_mode[myindex].xres > 1280) return -1;
853 static void XGIfb_search_crt2type(const char *name)
860 while(XGI_crt2type[i].type_no != -1) {
861 if (!strcmp(name, XGI_crt2type[i].name)) {
862 XGIfb_crt2type = XGI_crt2type[i].type_no;
863 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
868 if(XGIfb_crt2type < 0)
869 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
872 static void XGIfb_search_queuemode(const char *name)
879 while (XGI_queuemode[i].type_no != -1) {
880 if (!strcmp(name, XGI_queuemode[i].name)) {
881 XGIfb_queuemode = XGI_queuemode[i].type_no;
886 if (XGIfb_queuemode < 0)
887 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
890 static u8 XGIfb_search_refresh_rate(unsigned int rate)
895 xres = XGIbios_mode[xgifb_mode_idx].xres;
896 yres = XGIbios_mode[xgifb_mode_idx].yres;
899 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
900 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
901 if (XGIfb_vrate[i].refresh == rate) {
902 XGIfb_rate_idx = XGIfb_vrate[i].idx;
904 } else if (XGIfb_vrate[i].refresh > rate) {
905 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
906 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
907 rate, XGIfb_vrate[i].refresh);
908 XGIfb_rate_idx = XGIfb_vrate[i].idx;
909 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
910 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
911 && (XGIfb_vrate[i].idx != 1)) {
912 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
913 rate, XGIfb_vrate[i-1].refresh);
914 XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
915 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
918 } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
919 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
920 rate, XGIfb_vrate[i].refresh);
921 XGIfb_rate_idx = XGIfb_vrate[i].idx;
927 if (XGIfb_rate_idx > 0) {
928 return XGIfb_rate_idx;
931 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
936 static void XGIfb_search_tvstd(const char *name)
943 while (XGI_tvtype[i].type_no != -1) {
944 if (!strcmp(name, XGI_tvtype[i].name)) {
945 XGIfb_tvmode = XGI_tvtype[i].type_no;
952 static BOOLEAN XGIfb_bridgeisslave(void)
954 unsigned char usScratchP1_00;
956 if (xgi_video_info.hasVB == HASVB_NONE)
959 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
960 if ((usScratchP1_00 & 0x50) == 0x10)
966 static BOOLEAN XGIfbcheckvretracecrt1(void)
970 inXGIIDXREG(XGICR,0x17,temp);
975 inXGIIDXREG(XGISR,0x1f,temp);
979 if (inXGIREG(XGIINPSTAT) & 0x08)
985 static BOOLEAN XGIfbcheckvretracecrt2(void)
988 if (xgi_video_info.hasVB == HASVB_NONE)
990 inXGIIDXREG(XGIPART1, 0x30, temp);
997 static BOOLEAN XGIfb_CheckVBRetrace(void)
999 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1000 if(XGIfb_bridgeisslave()) {
1001 return(XGIfbcheckvretracecrt1());
1003 return(XGIfbcheckvretracecrt2());
1006 return(XGIfbcheckvretracecrt1());
1009 /* ----------- FBDev related routines for all series ----------- */
1012 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1014 switch(var->bits_per_pixel) {
1016 var->red.offset = var->green.offset = var->blue.offset = 0;
1017 var->red.length = var->green.length = var->blue.length = 6;
1018 xgi_video_info.video_cmap_len = 256;
1021 var->red.offset = 11;
1022 var->red.length = 5;
1023 var->green.offset = 5;
1024 var->green.length = 6;
1025 var->blue.offset = 0;
1026 var->blue.length = 5;
1027 var->transp.offset = 0;
1028 var->transp.length = 0;
1029 xgi_video_info.video_cmap_len = 16;
1032 var->red.offset = 16;
1033 var->red.length = 8;
1034 var->green.offset = 8;
1035 var->green.length = 8;
1036 var->blue.offset = 0;
1037 var->blue.length = 8;
1038 var->transp.offset = 24;
1039 var->transp.length = 8;
1040 xgi_video_info.video_cmap_len = 16;
1047 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1048 struct fb_info *info)
1051 unsigned int htotal = var->left_margin + var->xres +
1052 var->right_margin + var->hsync_len;
1053 unsigned int vtotal = var->upper_margin + var->yres +
1054 var->lower_margin + var->vsync_len;
1055 #if defined(__powerpc__)
1056 u8 sr_data, cr_data;
1058 unsigned int drate = 0, hrate = 0;
1061 // unsigned char reg,reg1;
1063 DEBUGPRN("Inside do_set_var");
1064 // 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);
1066 info->var.xres_virtual = var->xres_virtual;
1067 info->var.yres_virtual = var->yres_virtual;
1068 info->var.bits_per_pixel = var->bits_per_pixel;
1070 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1072 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1074 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1080 if(!htotal || !vtotal) {
1081 DPRINTK("XGIfb: Invalid 'var' information\n");
1084 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1085 var->pixclock,htotal,vtotal);
1089 if(var->pixclock && htotal && vtotal) {
1090 drate = 1000000000 / var->pixclock;
1091 hrate = (drate * 1000) / htotal;
1092 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1094 xgi_video_info.refresh_rate = 60;
1097 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1098 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1100 old_mode = xgifb_mode_idx;
1103 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1104 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1105 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1106 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1107 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1108 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1116 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1118 xgifb_mode_idx = -1;
1120 if(xgifb_mode_idx < 0) {
1121 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1122 var->yres, var->bits_per_pixel);
1123 xgifb_mode_idx = old_mode;
1127 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1128 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1129 xgi_video_info.refresh_rate = 60;
1135 XGIfb_pre_setmode();
1136 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1137 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1140 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1142 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1144 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1145 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1147 XGIfb_post_setmode();
1149 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1150 XGIbios_mode[xgifb_mode_idx].xres,
1151 XGIbios_mode[xgifb_mode_idx].yres,
1152 XGIbios_mode[xgifb_mode_idx].bpp,
1153 xgi_video_info.refresh_rate);
1155 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1156 xgi_video_info.video_vwidth = info->var.xres_virtual;
1157 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1158 xgi_video_info.video_vheight = info->var.yres_virtual;
1159 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1160 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1161 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1162 xgi_video_info.accel = 0;
1164 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1166 switch(xgi_video_info.video_bpp)
1169 xgi_video_info.DstColor = 0x0000;
1170 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1171 xgi_video_info.video_cmap_len = 256;
1172 #if defined(__powerpc__)
1173 inXGIIDXREG (XGICR, 0x4D, cr_data);
1174 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1178 xgi_video_info.DstColor = 0x8000;
1179 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1180 #if defined(__powerpc__)
1181 inXGIIDXREG (XGICR, 0x4D, cr_data);
1182 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1184 xgi_video_info.video_cmap_len = 16;
1187 xgi_video_info.DstColor = 0xC000;
1188 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1189 xgi_video_info.video_cmap_len = 16;
1190 #if defined(__powerpc__)
1191 inXGIIDXREG (XGICR, 0x4D, cr_data);
1192 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1196 xgi_video_info.video_cmap_len = 16;
1197 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1198 xgi_video_info.accel = 0;
1202 XGIfb_bpp_to_var(var); /*update ARGB info*/
1203 DEBUGPRN("End of do_set_var");
1210 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1214 // printk("Inside pan_var");
1216 if (var->xoffset > (var->xres_virtual - var->xres)) {
1217 // printk( "Pan: xo: %d xv %d xr %d\n",
1218 // var->xoffset, var->xres_virtual, var->xres);
1221 if(var->yoffset > (var->yres_virtual - var->yres)) {
1222 // printk( "Pan: yo: %d yv %d yr %d\n",
1223 // var->yoffset, var->yres_virtual, var->yres);
1226 base = var->yoffset * var->xres_virtual + var->xoffset;
1228 /* calculate base bpp dep. */
1229 switch(var->bits_per_pixel) {
1241 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1243 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1244 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1245 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1246 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1247 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1249 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1250 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1251 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1252 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1253 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1254 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1256 // printk("End of pan_var");
1262 void XGI_dispinfo(struct ap_data *rec)
1264 rec->minfo.bpp = xgi_video_info.video_bpp;
1265 rec->minfo.xres = xgi_video_info.video_width;
1266 rec->minfo.yres = xgi_video_info.video_height;
1267 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1268 rec->minfo.v_yres = xgi_video_info.video_vheight;
1269 rec->minfo.org_x = xgi_video_info.org_x;
1270 rec->minfo.org_y = xgi_video_info.org_y;
1271 rec->minfo.vrate = xgi_video_info.refresh_rate;
1272 rec->iobase = xgi_video_info.vga_base - 0x30;
1273 rec->mem_size = xgi_video_info.video_size;
1274 rec->disp_state = xgi_video_info.disp_state;
1275 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1276 rec->hasVB = xgi_video_info.hasVB;
1277 rec->TV_type = xgi_video_info.TV_type;
1278 rec->TV_plug = xgi_video_info.TV_plug;
1279 rec->chip = xgi_video_info.chip;
1285 static int XGIfb_open(struct fb_info *info, int user)
1290 static int XGIfb_release(struct fb_info *info, int user)
1295 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1299 switch(var->bits_per_pixel) {
1313 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1314 unsigned transp, struct fb_info *info)
1316 if (regno >= XGIfb_get_cmap_len(&info->var))
1319 switch (info->var.bits_per_pixel) {
1321 outXGIREG(XGIDACA, regno);
1322 outXGIREG(XGIDACD, (red >> 10));
1323 outXGIREG(XGIDACD, (green >> 10));
1324 outXGIREG(XGIDACD, (blue >> 10));
1325 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1326 outXGIREG(XGIDAC2A, regno);
1327 outXGIREG(XGIDAC2D, (red >> 8));
1328 outXGIREG(XGIDAC2D, (green >> 8));
1329 outXGIREG(XGIDAC2D, (blue >> 8));
1333 ((u32 *)(info->pseudo_palette))[regno] =
1334 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1340 ((u32 *) (info->pseudo_palette))[regno] =
1341 (red << 16) | (green << 8) | (blue);
1347 static int XGIfb_set_par(struct fb_info *info)
1351 // printk("XGIfb: inside set_par\n");
1352 if((err = XGIfb_do_set_var(&info->var, 1, info)))
1354 XGIfb_get_fix(&info->fix, -1, info);
1355 // printk("XGIfb:end of set_par\n");
1359 static int XGIfb_check_var(struct fb_var_screeninfo *var,
1360 struct fb_info *info)
1362 unsigned int htotal =
1363 var->left_margin + var->xres + var->right_margin +
1365 unsigned int vtotal = 0;
1366 unsigned int drate = 0, hrate = 0;
1368 int refresh_rate, search_idx;
1370 DEBUGPRN("Inside check_var");
1372 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1373 vtotal = var->upper_margin + var->yres + var->lower_margin +
1376 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1377 vtotal = var->upper_margin + var->yres + var->lower_margin +
1380 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1381 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1383 } else vtotal = var->upper_margin + var->yres + var->lower_margin +
1386 if(!(htotal) || !(vtotal)) {
1387 XGIFAIL("XGIfb: no valid timing data");
1391 if(var->pixclock && htotal && vtotal) {
1392 drate = 1000000000 / var->pixclock;
1393 hrate = (drate * 1000) / htotal;
1394 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1396 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1397 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1398 __func__,var->pixclock, htotal, vtotal,
1399 __func__, drate, hrate, xgi_video_info.refresh_rate);
1401 xgi_video_info.refresh_rate = 60;
1405 if((var->pixclock) && (htotal)) {
1406 drate = 1E12 / var->pixclock;
1407 hrate = drate / htotal;
1408 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1409 } else refresh_rate = 60;
1411 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1412 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1415 while((XGIbios_mode[search_idx].mode_no != 0) &&
1416 (XGIbios_mode[search_idx].xres <= var->xres) ) {
1417 if((XGIbios_mode[search_idx].xres == var->xres) &&
1418 (XGIbios_mode[search_idx].yres == var->yres) &&
1419 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1420 if(XGIfb_validate_mode(search_idx) > 0) {
1430 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1431 var->xres, var->yres, var->bits_per_pixel);
1434 while(XGIbios_mode[search_idx].mode_no != 0) {
1436 if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1437 (var->yres <= XGIbios_mode[search_idx].yres) &&
1438 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1439 if(XGIfb_validate_mode(search_idx) > 0) {
1447 var->xres = XGIbios_mode[search_idx].xres;
1448 var->yres = XGIbios_mode[search_idx].yres;
1449 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1450 var->xres, var->yres, var->bits_per_pixel);
1453 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1454 var->xres, var->yres, var->bits_per_pixel);
1459 /* TW: TODO: Check the refresh rate */
1461 /* Adapt RGB settings */
1462 XGIfb_bpp_to_var(var);
1464 /* Sanity check for offsets */
1465 if (var->xoffset < 0)
1467 if (var->yoffset < 0)
1472 if(var->xres != var->xres_virtual)
1473 var->xres_virtual = var->xres;
1474 if(var->yres != var->yres_virtual)
1475 var->yres_virtual = var->yres;
1477 // TW: Now patch yres_virtual if we use panning
1479 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1480 if(var->yres_virtual <= var->yres) {
1481 // TW: Paranoia check
1482 var->yres_virtual = var->yres;
1486 /* Truncate offsets to maximum if too high */
1487 if (var->xoffset > var->xres_virtual - var->xres)
1488 var->xoffset = var->xres_virtual - var->xres - 1;
1490 if (var->yoffset > var->yres_virtual - var->yres)
1491 var->yoffset = var->yres_virtual - var->yres - 1;
1493 /* Set everything else to 0 */
1494 var->red.msb_right =
1495 var->green.msb_right =
1496 var->blue.msb_right =
1497 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1499 DEBUGPRN("end of check_var");
1504 static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1505 struct fb_info* info)
1509 // printk("\nInside pan_display:");
1511 if (var->xoffset > (var->xres_virtual - var->xres))
1513 if (var->yoffset > (var->yres_virtual - var->yres))
1516 if (var->vmode & FB_VMODE_YWRAP) {
1517 if (var->yoffset < 0
1518 || var->yoffset >= info->var.yres_virtual
1519 || var->xoffset) return -EINVAL;
1521 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1522 var->yoffset + info->var.yres > info->var.yres_virtual)
1526 if((err = XGIfb_pan_var(var)) < 0) return err;
1528 info->var.xoffset = var->xoffset;
1529 info->var.yoffset = var->yoffset;
1530 if (var->vmode & FB_VMODE_YWRAP)
1531 info->var.vmode |= FB_VMODE_YWRAP;
1533 info->var.vmode &= ~FB_VMODE_YWRAP;
1535 // printk(" End of pan_display");
1541 static int XGIfb_mmap(struct fb_info *info, struct file *file,
1542 struct vm_area_struct *vma)
1544 unsigned long start;
1548 DEBUGPRN("inside mmap");
1549 if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
1551 off = vma->vm_pgoff << PAGE_SHIFT;
1553 start = (unsigned long) xgi_video_info.video_base;
1554 len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size);
1560 /* By Jake Page: Treat mmap request with offset beyond heapstart
1561 * as request for mapping the mmio area
1564 mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart);
1565 if(off >= mmio_off) {
1567 if(info->var.accel_flags) return -EINVAL;
1569 start = (unsigned long) xgi_video_info.mmio_base;
1570 len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size);
1574 if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL;
1577 vma->vm_pgoff = off >> PAGE_SHIFT;
1578 vma->vm_flags |= VM_IO; /* by Jake Page; is that really needed? */
1580 #if defined(__i386__) || defined(__x86_64__)
1581 if (boot_cpu_data.x86 > 3)
1582 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
1584 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
1588 DEBUGPRN("end of mmap");
1592 static int XGIfb_blank(int blank, struct fb_info *info)
1596 inXGIIDXREG(XGICR, 0x17, reg);
1603 outXGIIDXREG(XGICR, 0x17, reg);
1604 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1605 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1610 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1613 DEBUGPRN("inside ioctl");
1616 if (!capable(CAP_SYS_RAWIO))
1618 XGI_malloc((struct XGI_memreq *) arg);
1621 if (!capable(CAP_SYS_RAWIO))
1623 XGI_free(*(unsigned long *) arg);
1625 case FBIOGET_HWCINFO:
1627 unsigned long *hwc_offset = (unsigned long *) arg;
1629 if (XGIfb_caps & HW_CURSOR_CAP)
1630 *hwc_offset = XGIfb_hwcursor_vbase -
1631 (unsigned long) xgi_video_info.video_vbase;
1637 case FBIOPUT_MODEINFO:
1639 struct mode_info *x = (struct mode_info *)arg;
1641 xgi_video_info.video_bpp = x->bpp;
1642 xgi_video_info.video_width = x->xres;
1643 xgi_video_info.video_height = x->yres;
1644 xgi_video_info.video_vwidth = x->v_xres;
1645 xgi_video_info.video_vheight = x->v_yres;
1646 xgi_video_info.org_x = x->org_x;
1647 xgi_video_info.org_y = x->org_y;
1648 xgi_video_info.refresh_rate = x->vrate;
1649 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1650 switch(xgi_video_info.video_bpp) {
1652 xgi_video_info.DstColor = 0x0000;
1653 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1654 xgi_video_info.video_cmap_len = 256;
1657 xgi_video_info.DstColor = 0x8000;
1658 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1659 xgi_video_info.video_cmap_len = 16;
1662 xgi_video_info.DstColor = 0xC000;
1663 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1664 xgi_video_info.video_cmap_len = 16;
1667 xgi_video_info.video_cmap_len = 16;
1668 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1669 xgi_video_info.accel = 0;
1675 case FBIOGET_DISPINFO:
1676 XGI_dispinfo((struct ap_data *)arg);
1678 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1680 XGIfb_info *x = (XGIfb_info *)arg;
1682 //x->XGIfb_id = XGIFB_ID;
1683 x->XGIfb_version = VER_MAJOR;
1684 x->XGIfb_revision = VER_MINOR;
1685 x->XGIfb_patchlevel = VER_LEVEL;
1686 x->chip_id = xgi_video_info.chip_id;
1687 x->memory = xgi_video_info.video_size / 1024;
1688 x->heapstart = xgi_video_info.heapstart / 1024;
1689 x->fbvidmode = XGIfb_mode_no;
1690 x->XGIfb_caps = XGIfb_caps;
1691 x->XGIfb_tqlen = 512; /* yet unused */
1692 x->XGIfb_pcibus = xgi_video_info.pcibus;
1693 x->XGIfb_pcislot = xgi_video_info.pcislot;
1694 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1695 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1696 x->XGIfb_lcda = XGIfb_detectedlcda;
1699 case XGIFB_GET_VBRSTATUS:
1701 unsigned long *vbrstatus = (unsigned long *) arg;
1702 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1703 else *vbrstatus = 0;
1708 DEBUGPRN("end of ioctl");
1715 /* ----------- FBDev related routines for all series ---------- */
1717 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1718 struct fb_info *info)
1720 DEBUGPRN("inside get_fix");
1721 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1723 strcpy(fix->id, myid);
1725 fix->smem_start = xgi_video_info.video_base;
1727 fix->smem_len = xgi_video_info.video_size;
1730 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1731 if (xgi_video_info.video_size > 0x1000000) {
1732 fix->smem_len = 0xD00000;
1733 } else if (xgi_video_info.video_size > 0x800000)
1734 fix->smem_len = 0x800000;
1736 fix->smem_len = 0x400000;
1738 fix->smem_len = XGIfb_mem * 1024;
1740 fix->type = video_type;
1742 if(xgi_video_info.video_bpp == 8)
1743 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1745 fix->visual = FB_VISUAL_DIRECTCOLOR;
1748 if(XGIfb_ypan) fix->ypanstep = 1;
1751 fix->line_length = xgi_video_info.video_linelength;
1752 fix->mmio_start = xgi_video_info.mmio_base;
1753 fix->mmio_len = XGIfb_mmio_size;
1754 if(xgi_video_info.chip >= XG40)
1755 fix->accel = FB_ACCEL_XGI_XABRE;
1757 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1760 DEBUGPRN("end of get_fix");
1765 static struct fb_ops XGIfb_ops = {
1766 .owner = THIS_MODULE,
1767 .fb_open = XGIfb_open,
1768 .fb_release = XGIfb_release,
1769 .fb_check_var = XGIfb_check_var,
1770 .fb_set_par = XGIfb_set_par,
1771 .fb_setcolreg = XGIfb_setcolreg,
1773 .fb_pan_display = XGIfb_pan_display,
1775 .fb_blank = XGIfb_blank,
1776 .fb_fillrect = fbcon_XGI_fillrect,
1777 .fb_copyarea = fbcon_XGI_copyarea,
1778 .fb_imageblit = cfb_imageblit,
1779 .fb_sync = fbcon_XGI_sync,
1780 .fb_ioctl = XGIfb_ioctl,
1781 // .fb_mmap = XGIfb_mmap,
1784 /* ---------------- Chip generation dependent routines ---------------- */
1787 /* for XGI 315/550/650/740/330 */
1789 static int XGIfb_get_dram_size(void)
1795 /* xorg driver sets 32MB * 1 channel */
1796 if (xgi_video_info.chip == XG27)
1797 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1799 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1800 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1801 case XGI_DRAM_SIZE_1MB:
1802 xgi_video_info.video_size = 0x100000;
1804 case XGI_DRAM_SIZE_2MB:
1805 xgi_video_info.video_size = 0x200000;
1807 case XGI_DRAM_SIZE_4MB:
1808 xgi_video_info.video_size = 0x400000;
1810 case XGI_DRAM_SIZE_8MB:
1811 xgi_video_info.video_size = 0x800000;
1813 case XGI_DRAM_SIZE_16MB:
1814 xgi_video_info.video_size = 0x1000000;
1816 case XGI_DRAM_SIZE_32MB:
1817 xgi_video_info.video_size = 0x2000000;
1819 case XGI_DRAM_SIZE_64MB:
1820 xgi_video_info.video_size = 0x4000000;
1822 case XGI_DRAM_SIZE_128MB:
1823 xgi_video_info.video_size = 0x8000000;
1825 case XGI_DRAM_SIZE_256MB:
1826 xgi_video_info.video_size = 0x10000000;
1832 tmp = (reg & 0x0c) >> 2;
1833 switch(xgi_video_info.chip)
1874 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1875 //PLiad fixed for benchmarking and fb set
1876 //xgi_video_info.video_size = 0x200000;//1024x768x16
1877 //xgi_video_info.video_size = 0x1000000;//benchmark
1879 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1884 static void XGIfb_detect_VB(void)
1888 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1890 switch(xgi_video_info.hasVB) {
1891 case HASVB_LVDS_CHRONTEL:
1892 case HASVB_CHRONTEL:
1896 // XGI_Sense30x(); //Yi-Lin TV Sense?
1900 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1902 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1911 if (XGIfb_crt2type != -1)
1912 /* TW: Override with option */
1913 xgi_video_info.disp_state = XGIfb_crt2type;
1914 else if (cr32 & XGI_VB_TV)
1915 xgi_video_info.disp_state = DISPTYPE_TV;
1916 else if (cr32 & XGI_VB_LCD)
1917 xgi_video_info.disp_state = DISPTYPE_LCD;
1918 else if (cr32 & XGI_VB_CRT2)
1919 xgi_video_info.disp_state = DISPTYPE_CRT2;
1921 xgi_video_info.disp_state = 0;
1923 if(XGIfb_tvplug != -1)
1924 /* PR/TW: Override with option */
1925 xgi_video_info.TV_plug = XGIfb_tvplug;
1926 else if (cr32 & XGI_VB_HIVISION) {
1927 xgi_video_info.TV_type = TVMODE_HIVISION;
1928 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1930 else if (cr32 & XGI_VB_SVIDEO)
1931 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1932 else if (cr32 & XGI_VB_COMPOSITE)
1933 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1934 else if (cr32 & XGI_VB_SCART)
1935 xgi_video_info.TV_plug = TVPLUG_SCART;
1937 if(xgi_video_info.TV_type == 0) {
1938 /* TW: PAL/NTSC changed for 650 */
1939 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1941 inXGIIDXREG(XGICR, 0x38, temp);
1943 xgi_video_info.TV_type = TVMODE_PAL;
1945 xgi_video_info.TV_type = TVMODE_NTSC;
1949 inXGIIDXREG(XGICR, 0x79, temp);
1951 xgi_video_info.TV_type = TVMODE_PAL;
1953 xgi_video_info.TV_type = TVMODE_NTSC;
1957 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1958 if (XGIfb_forcecrt1 != -1) {
1959 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1960 else XGIfb_crt1off = 1;
1964 static void XGIfb_get_VB_type(void)
1968 if (!XGIfb_has_VB()) {
1969 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1970 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1971 case XGI310_EXTERNAL_CHIP_LVDS:
1972 xgi_video_info.hasVB = HASVB_LVDS;
1974 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1975 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1984 static int XGIfb_has_VB(void)
1988 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1989 switch (vb_chipid) {
1991 xgi_video_info.hasVB = HASVB_301;
1994 xgi_video_info.hasVB = HASVB_302;
1997 xgi_video_info.hasVB = HASVB_NONE;
2005 /* ------------------ Sensing routines ------------------ */
2007 /* TW: Determine and detect attached devices on XGI30x */
2009 XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
2013 outXGIIDXREG(XGIPART4,0x11,tempbl);
2014 temp = tempbh | tempcl;
2015 setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
2016 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
2018 inXGIIDXREG(XGIPART4,0x03,temp);
2028 u8 testsvhs_tempbl, testsvhs_tempbh;
2029 u8 testsvhs_tempcl, testsvhs_tempch;
2030 u8 testcvbs_tempbl, testcvbs_tempbh;
2031 u8 testcvbs_tempcl, testcvbs_tempch;
2032 u8 testvga2_tempbl, testvga2_tempbh;
2033 u8 testvga2_tempcl, testvga2_tempch;
2036 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2037 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
2041 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
2042 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
2043 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
2044 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
2045 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
2046 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
2047 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
2048 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
2049 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
2050 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2051 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2052 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
2053 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
2056 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
2057 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
2058 inXGIIDXREG(XGIPART4,0x01,myflag);
2060 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
2061 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
2062 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2065 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2066 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2067 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2068 testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2069 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2070 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2072 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2073 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2074 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2078 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2079 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2080 testvga2_tempcl, testvga2_tempch);
2082 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2083 orXGIIDXREG(XGICR, 0x32, 0x10);
2087 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2088 testsvhs_tempcl, testsvhs_tempch);
2090 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2091 /* TW: So we can be sure that there IS a SVHS output */
2092 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2093 orXGIIDXREG(XGICR, 0x32, 0x02);
2097 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2098 testcvbs_tempcl, testcvbs_tempch);
2100 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2101 /* TW: So we can be sure that there IS a CVBS output */
2102 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2103 orXGIIDXREG(XGICR, 0x32, 0x01);
2106 XGIDoSense(0, 0, 0, 0);
2108 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2113 /* ------------------------ Heap routines -------------------------- */
2115 static int XGIfb_heap_init(void)
2120 int agp_enabled = 1;
2122 unsigned long *cmdq_baseport = 0;
2123 unsigned long *read_port = 0;
2124 unsigned long *write_port = 0;
2125 XGI_CMDTYPE cmd_type;
2127 struct agp_kern_info *agp_info;
2128 struct agp_memory *agp;
2132 /* TW: The heap start is either set manually using the "mem" parameter, or
2133 * defaults as follows:
2134 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2135 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2136 * -) If 4MB or less is available, let it start at 4MB.
2137 * This is for avoiding a clash with X driver which uses the beginning
2138 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2140 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2141 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2143 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2144 if (xgi_video_info.video_size > 0x1000000) {
2145 xgi_video_info.heapstart = 0xD00000;
2146 } else if (xgi_video_info.video_size > 0x800000) {
2147 xgi_video_info.heapstart = 0x800000;
2149 xgi_video_info.heapstart = 0x400000;
2152 xgi_video_info.heapstart = XGIfb_mem * 1024;
2155 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2156 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2157 (int)(xgi_video_info.heapstart / 1024));
2159 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2160 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2164 /* TW: Now initialize the 310 series' command queue mode.
2165 * On 310/325, there are three queue modes available which
2166 * are chosen by setting bits 7:5 in SR26:
2167 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2168 * track of the queue, the FIFO, command parsing and so
2169 * on. This is the one comparable to the 300 series.
2170 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2171 * have to do queue management himself. Register 0x85c4 will
2172 * hold the location of the next free queue slot, 0x85c8
2173 * is the "queue read pointer" whose way of working is
2174 * unknown to me. Anyway, this mode would require a
2175 * translation of the MMIO commands to some kind of
2176 * accelerator assembly and writing these commands
2177 * to the memory location pointed to by 0x85c4.
2178 * We will not use this, as nobody knows how this
2179 * "assembly" works, and as it would require a complete
2180 * re-write of the accelerator code.
2181 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2182 * queue in AGP memory space.
2184 * SR26 bit 4 is called "Bypass H/W queue".
2185 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2186 * SR26 bit 0 resets the queue
2187 * Size of queue memory is encoded in bits 3:2 like this:
2192 * The queue location is to be written to 0x85C0.
2195 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2196 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2197 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2199 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2201 agp_size = COMMAND_QUEUE_AREA_SIZE;
2204 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2205 agp_info = vmalloc(sizeof(*agp_info));
2206 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2207 agp_copy_info(agp_info);
2209 agp_backend_acquire();
2211 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2214 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2217 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2218 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2219 /* TODO: Free AGP memory here */
2230 /* TW: Now select the queue mode */
2232 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2233 cmd_type = AGP_CMD_QUEUE;
2234 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2235 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2236 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2237 cmd_type = VM_CMD_QUEUE;
2238 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2240 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2241 cmd_type = MMIO_CMD;
2246 temp = XGI_CMD_QUEUE_SIZE_512k;
2249 temp = XGI_CMD_QUEUE_SIZE_1M;
2252 temp = XGI_CMD_QUEUE_SIZE_2M;
2255 temp = XGI_CMD_QUEUE_SIZE_4M;
2262 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2263 agp_info->aper_base, agp->physical, agp_size/1024);
2265 agp_phys = agp_info->aper_base + agp->physical;
2267 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2268 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2270 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2272 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2274 *write_port = *read_port;
2276 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2277 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2279 *cmdq_baseport = agp_phys;
2281 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2286 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2287 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2289 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2291 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2293 *write_port = *read_port;
2295 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2296 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2298 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2300 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2302 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2303 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2308 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2309 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2310 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2311 * enough. Reserve memory in any way.
2313 // FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2314 // FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2316 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2317 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2319 // FIXME *write_port = *read_port;
2321 // FIXME /* TW: Set Auto_Correction bit */
2322 // FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2323 // FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2325 // FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2327 // FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2329 // FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2330 // FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2337 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2338 top of the videoRAM, right below the TB memory area (if used). */
2339 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2340 XGIfb_heap_end -= XGIfb_hwcursor_size;
2341 XGIfb_heap_size -= XGIfb_hwcursor_size;
2342 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2344 XGIfb_caps |= HW_CURSOR_CAP;
2346 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2347 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2350 XGIfb_heap.poha_chain = NULL;
2351 XGIfb_heap.poh_freelist = NULL;
2353 poh = XGIfb_poh_new_node();
2355 if(poh == NULL) return 1;
2357 poh->poh_next = &XGIfb_heap.oh_free;
2358 poh->poh_prev = &XGIfb_heap.oh_free;
2359 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2360 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2362 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2363 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2364 (unsigned int) poh->size / 1024);
2366 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2367 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2369 XGIfb_heap.oh_free.poh_next = poh;
2370 XGIfb_heap.oh_free.poh_prev = poh;
2371 XGIfb_heap.oh_free.size = 0;
2372 XGIfb_heap.max_freesize = poh->size;
2374 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2375 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2376 XGIfb_heap.oh_used.size = SENTINEL;
2381 static XGI_OH *XGIfb_poh_new_node(void)
2388 if (XGIfb_heap.poh_freelist == NULL) {
2389 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2390 if(!poha) return NULL;
2392 poha->poha_next = XGIfb_heap.poha_chain;
2393 XGIfb_heap.poha_chain = poha;
2395 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2397 poh = &poha->aoh[0];
2398 for (i = cOhs - 1; i != 0; i--) {
2399 poh->poh_next = poh + 1;
2403 poh->poh_next = NULL;
2404 XGIfb_heap.poh_freelist = &poha->aoh[0];
2407 poh = XGIfb_heap.poh_freelist;
2408 XGIfb_heap.poh_freelist = poh->poh_next;
2413 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2419 if (size > XGIfb_heap.max_freesize) {
2420 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2421 (unsigned int) size / 1024);
2425 pohThis = XGIfb_heap.oh_free.poh_next;
2427 while (pohThis != &XGIfb_heap.oh_free) {
2428 if (size <= pohThis->size) {
2432 pohThis = pohThis->poh_next;
2436 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2437 (unsigned int) size / 1024);
2441 if (size == pohThis->size) {
2443 XGIfb_delete_node(pohThis);
2445 pohRoot = XGIfb_poh_new_node();
2447 if (pohRoot == NULL) {
2451 pohRoot->offset = pohThis->offset;
2452 pohRoot->size = size;
2454 pohThis->offset += size;
2455 pohThis->size -= size;
2458 XGIfb_heap.max_freesize -= size;
2460 pohThis = &XGIfb_heap.oh_used;
2461 XGIfb_insert_node(pohThis, pohRoot);
2466 static void XGIfb_delete_node(XGI_OH *poh)
2471 poh_prev = poh->poh_prev;
2472 poh_next = poh->poh_next;
2474 poh_prev->poh_next = poh_next;
2475 poh_next->poh_prev = poh_prev;
2479 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2483 pohTemp = pohList->poh_next;
2485 pohList->poh_next = poh;
2486 pohTemp->poh_prev = poh;
2488 poh->poh_prev = pohList;
2489 poh->poh_next = pohTemp;
2492 static XGI_OH *XGIfb_poh_free(unsigned long base)
2498 unsigned long ulUpper;
2499 unsigned long ulLower;
2502 poh_freed = XGIfb_heap.oh_used.poh_next;
2504 while(poh_freed != &XGIfb_heap.oh_used) {
2505 if(poh_freed->offset == base) {
2510 poh_freed = poh_freed->poh_next;
2513 if (!foundNode) return (NULL);
2515 XGIfb_heap.max_freesize += poh_freed->size;
2517 poh_prev = poh_next = NULL;
2518 ulUpper = poh_freed->offset + poh_freed->size;
2519 ulLower = poh_freed->offset;
2521 pohThis = XGIfb_heap.oh_free.poh_next;
2523 while (pohThis != &XGIfb_heap.oh_free) {
2524 if (pohThis->offset == ulUpper) {
2527 else if ((pohThis->offset + pohThis->size) ==
2531 pohThis = pohThis->poh_next;
2534 XGIfb_delete_node(poh_freed);
2536 if (poh_prev && poh_next) {
2537 poh_prev->size += (poh_freed->size + poh_next->size);
2538 XGIfb_delete_node(poh_next);
2539 XGIfb_free_node(poh_freed);
2540 XGIfb_free_node(poh_next);
2545 poh_prev->size += poh_freed->size;
2546 XGIfb_free_node(poh_freed);
2551 poh_next->size += poh_freed->size;
2552 poh_next->offset = poh_freed->offset;
2553 XGIfb_free_node(poh_freed);
2557 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2562 static void XGIfb_free_node(XGI_OH *poh)
2564 if(poh == NULL) return;
2566 poh->poh_next = XGIfb_heap.poh_freelist;
2567 XGIfb_heap.poh_freelist = poh;
2571 void XGI_malloc(struct XGI_memreq *req)
2575 poh = XGIfb_poh_allocate(req->size);
2580 DPRINTK("XGIfb: Video RAM allocation failed\n");
2582 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2583 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2585 req->offset = poh->offset;
2586 req->size = poh->size;
2591 void XGI_free(unsigned long base)
2595 poh = XGIfb_poh_free(base);
2598 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2599 (unsigned int) base);
2603 /* --------------------- SetMode routines ------------------------- */
2605 static void XGIfb_pre_setmode(void)
2607 u8 cr30 = 0, cr31 = 0;
2609 inXGIIDXREG(XGICR, 0x31, cr31);
2612 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2614 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2615 cr31 |= XGI_DRIVER_MODE;
2618 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2619 cr31 |= XGI_DRIVER_MODE;
2622 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2623 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2624 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2625 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2626 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2627 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2628 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2629 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2630 cr31 |= XGI_DRIVER_MODE;
2632 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2637 default: /* disable CRT2 */
2639 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2642 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2643 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2644 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2646 if(xgi_video_info.accel) XGIfb_syncaccel();
2651 static void XGIfb_post_setmode(void)
2655 #if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */
2656 /* Backup mode number to MMIO space */
2657 if(xgi_video_info.mmio_vbase) {
2658 *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no;
2661 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2662 outXGIIDXREG(XGICR,0x13,0x00);
2663 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2665 if (xgi_video_info.video_bpp == 8) {
2666 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2667 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2670 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2671 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2676 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2677 if(xgi_video_info.hasVB != HASVB_NONE) {
2678 inXGIIDXREG(XGIPART1, 0x00, reg);
2681 if ((reg & 0x50) == 0x10)
2688 inXGIIDXREG(XGICR, 0x17, reg);
2689 if ((XGIfb_crt1off) && (doit))
2693 outXGIIDXREG(XGICR, 0x17, reg);
2695 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2697 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2699 inXGIIDXREG(XGIPART4, 0x01, reg);
2701 if(reg < 0xB0) { /* Set filter for XGI301 */
2703 switch (xgi_video_info.video_width) {
2705 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2708 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2711 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2714 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2721 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2723 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2725 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2727 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2729 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2731 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2733 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2735 switch (xgi_video_info.video_width) {
2737 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2738 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2739 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2740 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2743 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2744 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2745 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2746 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2749 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2750 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2751 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2752 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2757 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2759 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2761 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2763 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2765 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2767 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2769 switch (xgi_video_info.video_width) {
2771 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2772 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2773 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2774 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2777 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2778 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2779 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2780 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2783 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2784 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2785 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2786 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2792 if ((filter >= 0) && (filter <=7)) {
2793 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2794 XGI_TV_filter[filter_tb].filter[filter][0],
2795 XGI_TV_filter[filter_tb].filter[filter][1],
2796 XGI_TV_filter[filter_tb].filter[filter][2],
2797 XGI_TV_filter[filter_tb].filter[filter][3]
2799 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2800 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2801 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2802 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2812 XGIINITSTATIC int __init XGIfb_setup(char *options)
2818 xgi_video_info.refresh_rate = 0;
2820 printk(KERN_INFO "XGIfb: Options %s\n", options);
2822 if (!options || !*options)
2825 while((this_opt = strsep(&options, ",")) != NULL) {
2827 if (!*this_opt) continue;
2829 if (!strncmp(this_opt, "mode:", 5)) {
2830 XGIfb_search_mode(this_opt + 5);
2831 } else if (!strncmp(this_opt, "vesa:", 5)) {
2832 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2833 } else if (!strncmp(this_opt, "mode:", 5)) {
2834 XGIfb_search_mode(this_opt + 5);
2835 } else if (!strncmp(this_opt, "vesa:", 5)) {
2836 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2837 } else if (!strncmp(this_opt, "vrate:", 6)) {
2838 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2839 } else if (!strncmp(this_opt, "rate:", 5)) {
2840 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2841 } else if (!strncmp(this_opt, "off", 3)) {
2843 } else if (!strncmp(this_opt, "crt1off", 7)) {
2845 } else if (!strncmp(this_opt, "filter:", 7)) {
2846 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2847 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2848 XGIfb_search_crt2type(this_opt + 14);
2849 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2850 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2851 } else if (!strncmp(this_opt, "tvmode:",7)) {
2852 XGIfb_search_tvstd(this_opt + 7);
2853 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2854 XGIfb_search_tvstd(this_opt + 7);
2855 } else if (!strncmp(this_opt, "mem:",4)) {
2856 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2857 } else if (!strncmp(this_opt, "dstn", 4)) {
2859 /* TW: DSTN overrules forcecrt2type */
2860 XGIfb_crt2type = DISPTYPE_LCD;
2861 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2862 XGIfb_search_queuemode(this_opt + 10);
2863 } else if (!strncmp(this_opt, "pdc:", 4)) {
2864 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2865 if(XGIfb_pdc & ~0x3c) {
2866 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2869 } else if (!strncmp(this_opt, "noaccel", 7)) {
2871 } else if (!strncmp(this_opt, "noypan", 6)) {
2873 } else if (!strncmp(this_opt, "userom:", 7)) {
2874 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2875 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2876 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2878 XGIfb_search_mode(this_opt);
2879 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2882 /* TW: Acceleration only with MMIO mode */
2883 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2887 /* TW: Panning only with acceleration */
2888 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2891 printk("\nxgifb: outa xgifb_setup 3450");
2896 static unsigned char VBIOS_BUF[65535];
2898 unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
2901 u32 rom_address = 0;
2904 /* Get the size of the expansion rom */
2905 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2906 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2907 if ((rom_size & 0x01) == 0)
2913 rom_size &= 0xFFFFF800;
2914 rom_size = (~rom_size)+1;
2916 rom_address = pci_resource_start(dev, 0);
2917 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2919 printk("No suitable rom address found\n"); return NULL;
2922 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2925 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2927 /* memcpy(copy_address, rom_address, rom_size); */
2929 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2931 unsigned char *from = (unsigned char *)virt_addr;
2932 unsigned char *to = (unsigned char *)copy_address;
2933 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2936 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2938 printk("Copy is done\n");
2940 return copy_address;
2943 int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2951 XGIfb_registered = 0;
2953 memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
2954 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2955 if(!fb_info) return -ENOMEM;
2957 xgi_video_info.chip_id = pdev->device;
2958 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2959 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2960 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2961 XGIvga_enabled = reg16 & 0x01;
2963 xgi_video_info.pcibus = pdev->bus->number;
2964 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2965 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2966 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2967 xgi_video_info.subsysdevice = pdev->subsystem_device;
2969 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2970 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2971 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2972 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2973 XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base;
2974 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2975 printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2977 if (pci_enable_device(pdev))
2980 XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
2982 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2983 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2985 if(reg1 != 0xa1) /*I/O error */
2987 printk("\nXGIfb: I/O error!!!");
2991 switch (xgi_video_info.chip_id) {
2992 case PCI_DEVICE_ID_XG_20:
2993 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2994 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2995 if (CR48&GPIOG_READ)
2996 xgi_video_info.chip = XG21;
2998 xgi_video_info.chip = XG20;
2999 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3000 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3002 case PCI_DEVICE_ID_XG_40:
3003 xgi_video_info.chip = XG40;
3004 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3005 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3007 case PCI_DEVICE_ID_XG_41:
3008 xgi_video_info.chip = XG41;
3009 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3010 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3012 case PCI_DEVICE_ID_XG_42:
3013 xgi_video_info.chip = XG42;
3014 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3015 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3017 case PCI_DEVICE_ID_XG_27:
3018 xgi_video_info.chip = XG27;
3019 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3020 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3026 printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
3027 XGIhw_ext.jChipType = xgi_video_info.chip;
3029 switch (xgi_video_info.chip) {
3037 XGIhw_ext.bIntegratedMMEnabled = 1;
3045 XGIhw_ext.pDevice = NULL;
3046 if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
3048 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
3050 if(XGIhw_ext.pjVirtualRomBase)
3051 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
3053 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3055 XGIhw_ext.pjVirtualRomBase = NULL;
3056 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3058 XGIhw_ext.pjCustomizedROMImage = NULL;
3059 XGIhw_ext.bSkipDramSizing = 0;
3060 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3061 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
3062 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3065 XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
3066 if (XGIhw_ext.pSR == NULL)
3068 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3071 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3073 XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
3074 if (XGIhw_ext.pCR == NULL)
3076 vfree(XGIhw_ext.pSR);
3077 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3080 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3085 if (!XGIvga_enabled)
3087 /* Mapping Max FB Size for 315 Init */
3088 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3089 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3092 printk("XGIfb: XGIInit() ...");
3093 /* XGIInitNewt for LINUXBIOS only */
3094 if(XGIInitNew(&XGIhw_ext))
3104 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3112 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3113 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3116 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3118 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3119 // Set SR13 ,14 temporarily for UDtech
3120 outXGIIDXREG(XGISR, 0x13, 0x45);
3121 outXGIIDXREG(XGISR, 0x14, 0x51);
3127 if (XGIfb_get_dram_size())
3129 vfree(XGIhw_ext.pSR);
3130 vfree(XGIhw_ext.pCR);
3131 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3137 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3139 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3140 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3141 /* Enable 2D accelerator engine */
3142 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3145 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3147 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3148 { printk("unable request memory size %x",xgi_video_info.video_size);
3149 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3150 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3151 vfree(XGIhw_ext.pSR);
3152 vfree(XGIhw_ext.pCR);
3156 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3158 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3159 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3160 vfree(XGIhw_ext.pSR);
3161 vfree(XGIhw_ext.pCR);
3165 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3166 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3167 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3169 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3170 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3172 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3173 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3174 printk("XGIfb: XGIInitNew() ...");
3175 if(XGIInitNew(&XGIhw_ext))
3184 if(XGIfb_heap_init())
3186 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3190 xgi_video_info.mtrr = (unsigned int) 0;
3192 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3194 xgi_video_info.hasVB = HASVB_NONE;
3195 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3196 xgi_video_info.hasVB = HASVB_NONE;
3197 else if(xgi_video_info.chip == XG21) {
3198 inXGIIDXREG(XGICR,0x38,CR38);
3199 if ((CR38&0xE0) == 0xC0) {
3200 xgi_video_info.disp_state = DISPTYPE_LCD;
3201 if (!XGIfb_GetXG21LVDSData()) {
3203 for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
3204 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3205 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3206 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3211 else if ((CR38&0xE0) == 0x60)
3212 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3214 xgi_video_info.hasVB = HASVB_NONE;
3217 XGIfb_get_VB_type();
3219 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3221 XGIhw_ext.ulExternalChip = 0;
3223 switch (xgi_video_info.hasVB) {
3225 inXGIIDXREG(XGIPART4, 0x01, reg);
3227 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3228 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3229 } else if (reg >= 0xD0) {
3230 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3231 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3233 /* else if (reg >= 0xB0) {
3234 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3235 inXGIIDXREG(XGIPART4,0x23,reg1);
3236 printk("XGIfb: XGI301B bridge detected\n");
3239 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3240 printk("XGIfb: XGI301 bridge detected\n");
3244 inXGIIDXREG(XGIPART4, 0x01, reg);
3246 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3247 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3248 } else if (reg >= 0xD0) {
3249 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3250 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3251 } else if (reg >= 0xB0) {
3252 inXGIIDXREG(XGIPART4,0x23,reg1);
3254 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3257 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3258 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3262 XGIhw_ext.ulExternalChip = 0x1;
3263 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3265 case HASVB_TRUMPION:
3266 XGIhw_ext.ulExternalChip = 0x2;
3267 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3269 case HASVB_CHRONTEL:
3270 XGIhw_ext.ulExternalChip = 0x4;
3271 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3273 case HASVB_LVDS_CHRONTEL:
3274 XGIhw_ext.ulExternalChip = 0x5;
3275 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3278 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3282 if (xgi_video_info.hasVB != HASVB_NONE) {
3286 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3288 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3290 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3292 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3295 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3297 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3299 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3303 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3307 XGIfb_detectedpdc = 0;
3309 XGIfb_detectedlcda = 0xff;
3312 /* TW: Try to find about LCDA */
3314 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3315 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3316 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3319 inXGIIDXREG(XGICR,0x34,tmp);
3322 // Currently on LCDA? (Some BIOSes leave CR38)
3323 inXGIIDXREG(XGICR,0x38,tmp);
3324 if((tmp & 0x03) == 0x03)
3326 /* XGI_Pr.XGI_UseLCDA = 1; */
3329 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3330 inXGIIDXREG(XGICR,0x35,tmp);
3333 /* XGI_Pr.XGI_UseLCDA = 1; */
3336 inXGIIDXREG(XGICR,0x30,tmp);
3339 inXGIIDXREG(XGIPART1,0x13,tmp);
3342 /* XGI_Pr.XGI_UseLCDA = 1; */
3354 if (xgifb_mode_idx >= 0)
3355 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3357 if (xgifb_mode_idx < 0) {
3358 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3360 xgifb_mode_idx = DEFAULT_LCDMODE;
3361 if (xgi_video_info.chip == XG21)
3363 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3367 xgifb_mode_idx = DEFAULT_TVMODE;
3370 xgifb_mode_idx = DEFAULT_MODE;
3375 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3378 if( xgi_video_info.refresh_rate == 0)
3379 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3380 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3382 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3383 xgi_video_info.refresh_rate = 60;
3386 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3387 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3388 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3389 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3390 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3391 switch(xgi_video_info.video_bpp) {
3393 xgi_video_info.DstColor = 0x0000;
3394 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3395 xgi_video_info.video_cmap_len = 256;
3398 xgi_video_info.DstColor = 0x8000;
3399 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3400 xgi_video_info.video_cmap_len = 16;
3403 xgi_video_info.DstColor = 0xC000;
3404 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3405 xgi_video_info.video_cmap_len = 16;
3408 xgi_video_info.video_cmap_len = 16;
3409 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3415 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3416 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3417 xgi_video_info.refresh_rate);
3419 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3420 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3421 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3423 XGIfb_bpp_to_var(&default_var);
3425 default_var.pixclock = (u32) (1000000000 /
3426 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3427 XGIfb_mode_no, XGIfb_rate_idx));
3429 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3430 XGIfb_mode_no, XGIfb_rate_idx,
3431 &default_var.left_margin, &default_var.right_margin,
3432 &default_var.upper_margin, &default_var.lower_margin,
3433 &default_var.hsync_len, &default_var.vsync_len,
3434 &default_var.sync, &default_var.vmode)) {
3436 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3437 default_var.yres <<= 1;
3438 default_var.yres_virtual <<= 1;
3439 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3440 default_var.pixclock >>= 1;
3441 default_var.yres >>= 1;
3442 default_var.yres_virtual >>= 1;
3451 default_var.yres_virtual =
3452 xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
3453 if(default_var.yres_virtual <= default_var.yres) {
3454 default_var.yres_virtual = default_var.yres;
3461 xgi_video_info.accel = 0;
3463 xgi_video_info.accel = -1;
3464 default_var.accel_flags |= FB_ACCELF_TEXT;
3468 fb_info->flags = FBINFO_FLAG_DEFAULT;
3469 fb_info->var = default_var;
3470 fb_info->fix = XGIfb_fix;
3471 fb_info->par = &xgi_video_info;
3472 fb_info->screen_base = xgi_video_info.video_vbase;
3473 fb_info->fbops = &XGIfb_ops;
3474 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3475 fb_info->pseudo_palette = pseudo_palette;
3477 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3481 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3482 (unsigned int) xgi_video_info.video_size,
3483 MTRR_TYPE_WRCOMB, 1);
3484 if(xgi_video_info.mtrr) {
3485 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3489 if(register_framebuffer(fb_info) < 0)
3494 XGIfb_registered = 1;
3496 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
3499 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3500 XGIfb_accel ? "enabled" : "disabled",
3501 XGIfb_ypan ? "ypan" : "redraw");
3503 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3504 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3515 /*****************************************************/
3516 /* PCI DEVICE HANDLING */
3517 /*****************************************************/
3519 static void __devexit xgifb_remove(struct pci_dev *pdev)
3521 /* Unregister the framebuffer */
3522 // if(xgi_video_info.registered) {
3523 unregister_framebuffer(fb_info);
3524 framebuffer_release(fb_info);
3527 pci_set_drvdata(pdev, NULL);
3531 static struct pci_driver xgifb_driver = {
3533 .id_table = xgifb_pci_table,
3534 .probe = xgifb_probe,
3535 .remove = __devexit_p(xgifb_remove)
3538 XGIINITSTATIC int __init xgifb_init(void)
3541 char *option = NULL;
3543 if (fb_get_options("xgifb", &option))
3545 XGIfb_setup(option);
3547 return(pci_register_driver(&xgifb_driver));
3552 module_init(xgifb_init);
3555 /*****************************************************/
3557 /*****************************************************/
3561 static char *mode = NULL;
3562 static int vesa = 0;
3563 static unsigned int rate = 0;
3564 static unsigned int crt1off = 1;
3565 static unsigned int mem = 0;
3566 static char *forcecrt2type = NULL;
3567 static int forcecrt1 = -1;
3568 static int pdc = -1;
3569 static int pdc1 = -1;
3570 static int noaccel = -1;
3571 static int noypan = -1;
3572 static int nomax = -1;
3573 static int userom = -1;
3574 static int useoem = -1;
3575 static char *tvstandard = NULL;
3576 static int nocrt2rate = 0;
3577 static int scalelcd = -1;
3578 static char *specialtiming = NULL;
3579 static int lvdshl = -1;
3580 static int tvxposoffset = 0, tvyposoffset = 0;
3581 #if !defined(__i386__) && !defined(__x86_64__)
3582 static int resetcard = 0;
3583 static int videoram = 0;
3586 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3587 MODULE_LICENSE("GPL");
3588 MODULE_AUTHOR("XGITECH , Others");
3592 module_param(mem, int, 0);
3593 module_param(noaccel, int, 0);
3594 module_param(noypan, int, 0);
3595 module_param(nomax, int, 0);
3596 module_param(userom, int, 0);
3597 module_param(useoem, int, 0);
3598 module_param(mode, charp, 0);
3599 module_param(vesa, int, 0);
3600 module_param(rate, int, 0);
3601 module_param(forcecrt1, int, 0);
3602 module_param(forcecrt2type, charp, 0);
3603 module_param(scalelcd, int, 0);
3604 module_param(pdc, int, 0);
3605 module_param(pdc1, int, 0);
3606 module_param(specialtiming, charp, 0);
3607 module_param(lvdshl, int, 0);
3608 module_param(tvstandard, charp, 0);
3609 module_param(tvxposoffset, int, 0);
3610 module_param(tvyposoffset, int, 0);
3611 module_param(filter, int, 0);
3612 module_param(nocrt2rate, int, 0);
3613 #if !defined(__i386__) && !defined(__x86_64__)
3614 module_param(resetcard, int, 0);
3615 module_param(videoram, int, 0);
3619 MODULE_PARM_DESC(mem,
3620 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3621 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3622 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3623 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3624 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3625 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3626 "for XFree86 4.x/X.org 6.7 and later.\n");
3628 MODULE_PARM_DESC(noaccel,
3629 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3632 MODULE_PARM_DESC(noypan,
3633 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3634 "will be performed by redrawing the screen. (default: 0)\n");
3636 MODULE_PARM_DESC(nomax,
3637 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3638 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3639 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3640 "enable the user to positively specify a virtual Y size of the screen using\n"
3641 "fbset. (default: 0)\n");
3645 MODULE_PARM_DESC(mode,
3646 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3647 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3648 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3649 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3651 MODULE_PARM_DESC(vesa,
3652 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3653 "0x117 (default: 0x0103)\n");
3656 MODULE_PARM_DESC(rate,
3657 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3658 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3659 "will be ignored (default: 60)\n");
3661 MODULE_PARM_DESC(forcecrt1,
3662 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3663 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3664 "0=CRT1 OFF) (default: [autodetected])\n");
3666 MODULE_PARM_DESC(forcecrt2type,
3667 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3668 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3669 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3670 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3671 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3672 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3673 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3674 "depends on the very hardware in use. (default: [autodetected])\n");
3676 MODULE_PARM_DESC(scalelcd,
3677 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3678 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3679 "show black bars around the image, TMDS panels will probably do the scaling\n"
3680 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3682 MODULE_PARM_DESC(pdc,
3683 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3684 "should detect this correctly in most cases; however, sometimes this is not\n"
3685 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3686 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3687 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3688 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3690 MODULE_PARM_DESC(pdc1,
3691 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3692 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3693 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3694 "implemented yet.\n");
3696 MODULE_PARM_DESC(specialtiming,
3697 "\nPlease refer to documentation for more information on this option.\n");
3699 MODULE_PARM_DESC(lvdshl,
3700 "\nPlease refer to documentation for more information on this option.\n");
3702 MODULE_PARM_DESC(tvstandard,
3703 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3704 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3706 MODULE_PARM_DESC(tvxposoffset,
3707 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3710 MODULE_PARM_DESC(tvyposoffset,
3711 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3714 MODULE_PARM_DESC(filter,
3715 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3716 "(Possible values 0-7, default: [no filter])\n");
3718 MODULE_PARM_DESC(nocrt2rate,
3719 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3720 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3725 int __init xgifb_init_module(void)
3727 printk("\nXGIfb_init_module");
3729 XGIfb_search_mode(mode);
3730 else if (vesa != -1)
3731 XGIfb_search_vesamode(vesa);
3733 return(xgifb_init());
3736 static void __exit xgifb_remove_module(void)
3738 pci_unregister_driver(&xgifb_driver);
3739 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3742 module_init(xgifb_init_module);
3743 module_exit(xgifb_remove_module);
3745 #endif /* /MODULE */
3747 EXPORT_SYMBOL(XGI_malloc);
3748 EXPORT_SYMBOL(XGI_free);