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>
31 #include <linux/kernel.h>
51 #define Index_CR_GPIO_Reg1 0x48
52 #define Index_CR_GPIO_Reg2 0x49
53 #define Index_CR_GPIO_Reg3 0x4a
55 #define GPIOG_EN (1<<6)
56 #define GPIOG_WRITE (1<<6)
57 #define GPIOG_READ (1<<1)
58 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
60 /* -------------------- Macro definitions ---------------------------- */
65 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
67 #define DPRINTK(fmt, args...)
71 static void dumpVGAReg(void)
75 outXGIIDXREG(XGISR, 0x05, 0x86);
77 outXGIIDXREG(XGISR, 0x08, 0x4f);
78 outXGIIDXREG(XGISR, 0x0f, 0x20);
79 outXGIIDXREG(XGISR, 0x11, 0x4f);
80 outXGIIDXREG(XGISR, 0x13, 0x45);
81 outXGIIDXREG(XGISR, 0x14, 0x51);
82 outXGIIDXREG(XGISR, 0x1e, 0x41);
83 outXGIIDXREG(XGISR, 0x1f, 0x0);
84 outXGIIDXREG(XGISR, 0x20, 0xa1);
85 outXGIIDXREG(XGISR, 0x22, 0xfb);
86 outXGIIDXREG(XGISR, 0x26, 0x22);
87 outXGIIDXREG(XGISR, 0x3e, 0x07);
90 //outXGIIDXREG(XGICR, 0x19, 0x00);
91 //outXGIIDXREG(XGICR, 0x1a, 0x3C);
92 //outXGIIDXREG(XGICR, 0x22, 0xff);
93 //outXGIIDXREG(XGICR, 0x3D, 0x10);
95 //outXGIIDXREG(XGICR, 0x4a, 0xf3);
97 //outXGIIDXREG(XGICR, 0x57, 0x0);
98 //outXGIIDXREG(XGICR, 0x7a, 0x2c);
100 //outXGIIDXREG(XGICR, 0x82, 0xcc);
101 //outXGIIDXREG(XGICR, 0x8c, 0x0);
103 outXGIIDXREG(XGICR, 0x99, 0x1);
104 outXGIIDXREG(XGICR, 0x41, 0x40);
107 for(i=0; i < 0x4f; i++)
109 inXGIIDXREG(XGISR, i, reg);
110 printk("\no 3c4 %x",i);
111 printk("\ni 3c5 => %x",reg);
114 for(i=0; i < 0xF0; i++)
116 inXGIIDXREG(XGICR, i, reg);
117 printk("\no 3d4 %x",i);
118 printk("\ni 3d5 => %x",reg);
122 outXGIIDXREG(XGIPART1,0x2F,1);
123 for(i=1; i < 0x50; i++)
125 inXGIIDXREG(XGIPART1, i, reg);
126 printk("\no d004 %x",i);
127 printk("\ni d005 => %x",reg);
130 for(i=0; i < 0x50; i++)
132 inXGIIDXREG(XGIPART2, i, reg);
133 printk("\no d010 %x",i);
134 printk("\ni d011 => %x",reg);
136 for(i=0; i < 0x50; i++)
138 inXGIIDXREG(XGIPART3, i, reg);
139 printk("\no d012 %x",i);
140 printk("\ni d013 => %x",reg);
142 for(i=0; i < 0x50; i++)
144 inXGIIDXREG(XGIPART4, i, reg);
145 printk("\no d014 %x",i);
146 printk("\ni d015 => %x",reg);
151 static inline void dumpVGAReg(void) {}
154 /* data for XGI components */
155 struct video_info xgi_video_info;
161 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
165 /* --------------- Hardware Access Routines -------------------------- */
169 XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
170 unsigned char modeno, unsigned char rateindex)
172 USHORT ModeNo = modeno;
173 USHORT ModeIdIndex = 0, ClockIndex = 0;
174 USHORT RefreshRateTableIndex = 0;
178 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
179 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
181 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
184 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
186 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
190 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
191 RefreshRateTableIndex += (rateindex - 1);
194 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
195 if(HwDeviceExtension->jChipType < XGI_315H) {
198 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
204 XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
205 unsigned char modeno, unsigned char rateindex,
206 u32 *left_margin, u32 *right_margin,
207 u32 *upper_margin, u32 *lower_margin,
208 u32 *hsync_len, u32 *vsync_len,
209 u32 *sync, u32 *vmode)
211 USHORT ModeNo = modeno;
212 USHORT ModeIdIndex = 0, index = 0;
213 USHORT RefreshRateTableIndex = 0;
215 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
216 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
217 unsigned char sr_data, cr_data, cr_data2;
218 unsigned long cr_data3;
219 int A, B, C, D, E, F, temp, j;
220 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
221 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
222 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
224 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
227 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
228 RefreshRateTableIndex += (rateindex - 1);
230 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
232 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
234 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
236 /* Horizontal total */
237 HT = (cr_data & 0xff) |
238 ((unsigned short) (sr_data & 0x03) << 8);
241 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
243 Horizontal display enable end
244 HDE = (cr_data & 0xff) |
245 ((unsigned short) (sr_data & 0x0C) << 6);*/
246 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
249 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
251 /* Horizontal retrace (=sync) start */
252 HRS = (cr_data & 0xff) |
253 ((unsigned short) (sr_data & 0xC0) << 2);
256 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
258 /* Horizontal blank start */
259 HBS = (cr_data & 0xff) |
260 ((unsigned short) (sr_data & 0x30) << 4);
262 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
264 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
266 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
268 /* Horizontal blank end */
269 HBE = (cr_data & 0x1f) |
270 ((unsigned short) (cr_data2 & 0x80) >> 2) |
271 ((unsigned short) (sr_data & 0x03) << 6);
273 /* Horizontal retrace (=sync) end */
274 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
276 temp = HBE - ((E - 1) & 255);
277 B = (temp > 0) ? temp : (temp + 256);
279 temp = HRE - ((E + F + 3) & 63);
280 C = (temp > 0) ? temp : (temp + 64);
284 *left_margin = D * 8;
285 *right_margin = F * 8;
288 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
290 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
292 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
295 VT = (cr_data & 0xFF) |
296 ((unsigned short) (cr_data2 & 0x01) << 8) |
297 ((unsigned short)(cr_data2 & 0x20) << 4) |
298 ((unsigned short) (sr_data & 0x01) << 10);
301 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
303 /* Vertical display enable end */
304 /* VDE = (cr_data & 0xff) |
305 ((unsigned short) (cr_data2 & 0x02) << 7) |
306 ((unsigned short) (cr_data2 & 0x40) << 3) |
307 ((unsigned short) (sr_data & 0x02) << 9); */
308 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1;
311 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
313 /* Vertical retrace (=sync) start */
314 VRS = (cr_data & 0xff) |
315 ((unsigned short) (cr_data2 & 0x04) << 6) |
316 ((unsigned short) (cr_data2 & 0x80) << 2) |
317 ((unsigned short) (sr_data & 0x08) << 7);
320 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
322 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
324 /* Vertical blank start */
325 VBS = (cr_data & 0xff) |
326 ((unsigned short) (cr_data2 & 0x08) << 5) |
327 ((unsigned short) (cr_data3 & 0x20) << 4) |
328 ((unsigned short) (sr_data & 0x04) << 8);
330 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
332 /* Vertical blank end */
333 VBE = (cr_data & 0xff) |
334 ((unsigned short) (sr_data & 0x10) << 4);
335 temp = VBE - ((E - 1) & 511);
336 B = (temp > 0) ? temp : (temp + 512);
338 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
340 /* Vertical retrace (=sync) end */
341 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
342 temp = VRE - ((E + F - 1) & 31);
343 C = (temp > 0) ? temp : (temp + 32);
351 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
352 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
354 *sync |= FB_SYNC_VERT_HIGH_ACT;
356 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
357 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
359 *sync |= FB_SYNC_HOR_HIGH_ACT;
361 *vmode = FB_VMODE_NONINTERLACED;
362 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
363 *vmode = FB_VMODE_INTERLACED;
366 while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
367 if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
368 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
369 if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
370 *vmode = FB_VMODE_DOUBLE;
378 #if 0 /* That's bullshit, only the resolution needs to be shifted */
379 if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
383 } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
397 void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
399 XGI_Pr->RelIO = BaseAddr;
400 XGI_Pr->P3c4 = BaseAddr + 0x14;
401 XGI_Pr->P3d4 = BaseAddr + 0x24;
402 XGI_Pr->P3c0 = BaseAddr + 0x10;
403 XGI_Pr->P3ce = BaseAddr + 0x1e;
404 XGI_Pr->P3c2 = BaseAddr + 0x12;
405 XGI_Pr->P3ca = BaseAddr + 0x1a;
406 XGI_Pr->P3c6 = BaseAddr + 0x16;
407 XGI_Pr->P3c7 = BaseAddr + 0x17;
408 XGI_Pr->P3c8 = BaseAddr + 0x18;
409 XGI_Pr->P3c9 = BaseAddr + 0x19;
410 XGI_Pr->P3da = BaseAddr + 0x2A;
411 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
412 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
413 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
414 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
415 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
420 void XGIfb_set_reg4(u16 port, unsigned long data)
422 outl((u32) (data & 0xffffffff), port);
425 u32 XGIfb_get_reg3(u16 port)
433 /* ------------ Interface for init & mode switching code ------------- */
436 XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
437 unsigned long offset, unsigned long set, unsigned long *value)
439 static struct pci_dev *pdev = NULL;
440 static unsigned char init = 0, valid_pdev = 0;
443 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
445 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
449 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
457 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
458 xgi_video_info.chip_id);
463 pci_read_config_dword(pdev, offset, (u32 *)value);
465 pci_write_config_dword(pdev, offset, (u32)(*value));
470 /*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
471 unsigned long offset, unsigned long set, unsigned long *value)
473 static struct pci_dev *pdev = NULL;
474 static unsigned char init = 0, valid_pdev = 0;
479 switch (xgi_video_info.chip) {
481 nbridge_id = PCI_DEVICE_ID_XG_540;
484 nbridge_id = PCI_DEVICE_ID_XG_630;
487 nbridge_id = PCI_DEVICE_ID_XG_730;
490 nbridge_id = PCI_DEVICE_ID_XG_550;
493 nbridge_id = PCI_DEVICE_ID_XG_650;
496 nbridge_id = PCI_DEVICE_ID_XG_740;
503 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
509 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
515 pci_read_config_dword(pdev, offset, (u32 *)value);
517 pci_write_config_dword(pdev, offset, (u32)(*value));
522 /* ------------------ Internal helper routines ----------------- */
524 static void XGIfb_search_mode(const char *name)
529 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
530 xgifb_mode_idx = DEFAULT_MODE;
531 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
533 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
539 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
540 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
541 xgifb_mode_idx = DEFAULT_MODE;
542 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
544 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
549 while(XGIbios_mode[i].mode_no != 0) {
550 l = min(strlen(name), strlen(XGIbios_mode[i].name));
551 if (!strncmp(name, XGIbios_mode[i].name, l)) {
558 if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
561 static void XGIfb_search_vesamode(unsigned int vesamode)
567 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
568 xgifb_mode_idx = DEFAULT_MODE;
569 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
571 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
576 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
578 while(XGIbios_mode[i].mode_no != 0) {
579 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
580 (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
587 if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
590 int XGIfb_GetXG21LVDSData(void)
593 unsigned char *pData;
596 inXGIIDXREG(XGISR,0x1e,tmp);
597 outXGIIDXREG(XGISR, 0x1e, tmp|4);
599 pData = xgi_video_info.mmio_vbase+0x20000;
600 if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
602 i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
611 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
612 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
613 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
614 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
615 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
616 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
617 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
618 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
619 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
620 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
621 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
622 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
623 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
624 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
625 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
626 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
630 } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
636 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
640 int XGIfb_mode_idx = 0;
643 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
644 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
646 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
647 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
648 (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
650 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
659 return (XGIfb_mode_idx);
663 static int XGIfb_validate_mode(int myindex)
667 if (xgi_video_info.chip == XG21)
669 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
671 xres = XGI21_LCDCapList[0].LVDSHDE;
672 yres = XGI21_LCDCapList[0].LVDSVDE;
673 if(XGIbios_mode[myindex].xres > xres)
675 if(XGIbios_mode[myindex].yres > yres)
677 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
679 if (XGIbios_mode[myindex].bpp > 8)
688 /* FIXME: for now, all is valid on XG27 */
689 if (xgi_video_info.chip == XG27)
692 if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
695 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
697 switch (XGIhw_ext.ulCRT2LCDType) {
699 xres = 640; yres = 480; break;
701 xres = 800; yres = 600; break;
703 xres = 1024; yres = 600; break;
705 xres = 1024; yres = 768; break;
707 xres = 1152; yres = 768; break;
709 xres = 1280; yres = 960; break;
711 xres = 1280; yres = 768; break;
713 xres = 1280; yres = 1024; break;
715 xres = 1400; yres = 1050; break;
717 xres = 1600; yres = 1200; break;
718 // case LCD_320x480: // TW: FSTN
719 // xres = 320; yres = 480; break;
721 xres = 0; yres = 0; break;
723 if(XGIbios_mode[myindex].xres > xres) {
726 if(XGIbios_mode[myindex].yres > yres) {
729 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
730 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
732 switch (XGIbios_mode[myindex].xres) {
734 if(XGIbios_mode[myindex].yres != 512) return -1;
735 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
738 if((XGIbios_mode[myindex].yres != 400) &&
739 (XGIbios_mode[myindex].yres != 480))
743 if(XGIbios_mode[myindex].yres != 600) return -1;
746 if((XGIbios_mode[myindex].yres != 600) &&
747 (XGIbios_mode[myindex].yres != 768))
749 if((XGIbios_mode[myindex].yres == 600) &&
750 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
754 if((XGIbios_mode[myindex].yres) != 768) return -1;
755 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
758 if((XGIbios_mode[myindex].yres != 768) &&
759 (XGIbios_mode[myindex].yres != 1024))
761 if((XGIbios_mode[myindex].yres == 768) &&
762 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
766 if(XGIbios_mode[myindex].yres != 1050) return -1;
769 if(XGIbios_mode[myindex].yres != 1200) return -1;
775 switch (XGIbios_mode[myindex].xres) {
777 if(XGIbios_mode[myindex].yres != 512) return -1;
780 if((XGIbios_mode[myindex].yres != 400) &&
781 (XGIbios_mode[myindex].yres != 480))
785 if(XGIbios_mode[myindex].yres != 600) return -1;
788 if(XGIbios_mode[myindex].yres != 768) return -1;
791 if((XGIbios_mode[myindex].yres != 960) &&
792 (XGIbios_mode[myindex].yres != 1024))
794 if(XGIbios_mode[myindex].yres == 960) {
795 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
800 if(XGIbios_mode[myindex].yres != 1050) return -1;
803 if(XGIbios_mode[myindex].yres != 1200) return -1;
811 switch (XGIbios_mode[myindex].xres) {
817 if (xgi_video_info.TV_type == TVMODE_NTSC) {
818 if (XGIbios_mode[myindex].yres != 480) {
821 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
822 if (XGIbios_mode[myindex].yres != 576) {
826 // TW: LVDS/CHRONTEL does not support 720
827 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
828 xgi_video_info.hasVB == HASVB_CHRONTEL) {
833 if (xgi_video_info.TV_type == TVMODE_NTSC) {
834 if(XGIbios_mode[myindex].bpp == 32) {
838 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
839 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
840 xgi_video_info.hasVB == HASVB_CHRONTEL) {
841 if(xgi_video_info.chip < XGI_315H) {
851 if(XGIbios_mode[myindex].xres > 1280) return -1;
858 static void XGIfb_search_crt2type(const char *name)
865 while(XGI_crt2type[i].type_no != -1) {
866 if (!strcmp(name, XGI_crt2type[i].name)) {
867 XGIfb_crt2type = XGI_crt2type[i].type_no;
868 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
873 if(XGIfb_crt2type < 0)
874 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
877 static void XGIfb_search_queuemode(const char *name)
884 while (XGI_queuemode[i].type_no != -1) {
885 if (!strcmp(name, XGI_queuemode[i].name)) {
886 XGIfb_queuemode = XGI_queuemode[i].type_no;
891 if (XGIfb_queuemode < 0)
892 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
895 static u8 XGIfb_search_refresh_rate(unsigned int rate)
900 xres = XGIbios_mode[xgifb_mode_idx].xres;
901 yres = XGIbios_mode[xgifb_mode_idx].yres;
904 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
905 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
906 if (XGIfb_vrate[i].refresh == rate) {
907 XGIfb_rate_idx = XGIfb_vrate[i].idx;
909 } else if (XGIfb_vrate[i].refresh > rate) {
910 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
911 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
912 rate, XGIfb_vrate[i].refresh);
913 XGIfb_rate_idx = XGIfb_vrate[i].idx;
914 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
915 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
916 && (XGIfb_vrate[i].idx != 1)) {
917 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
918 rate, XGIfb_vrate[i-1].refresh);
919 XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
920 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
923 } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
924 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
925 rate, XGIfb_vrate[i].refresh);
926 XGIfb_rate_idx = XGIfb_vrate[i].idx;
932 if (XGIfb_rate_idx > 0) {
933 return XGIfb_rate_idx;
936 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
941 static void XGIfb_search_tvstd(const char *name)
948 while (XGI_tvtype[i].type_no != -1) {
949 if (!strcmp(name, XGI_tvtype[i].name)) {
950 XGIfb_tvmode = XGI_tvtype[i].type_no;
957 static BOOLEAN XGIfb_bridgeisslave(void)
959 unsigned char usScratchP1_00;
961 if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
963 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
964 if( (usScratchP1_00 & 0x50) == 0x10) {
971 static BOOLEAN XGIfbcheckvretracecrt1(void)
975 inXGIIDXREG(XGICR,0x17,temp);
976 if(!(temp & 0x80)) return FALSE;
979 inXGIIDXREG(XGISR,0x1f,temp);
980 if(temp & 0xc0) return FALSE;
983 if(inXGIREG(XGIINPSTAT) & 0x08) return TRUE;
987 static BOOLEAN XGIfbcheckvretracecrt2(void)
990 if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
991 inXGIIDXREG(XGIPART1, 0x30, temp);
992 if(temp & 0x02) return FALSE;
996 static BOOLEAN XGIfb_CheckVBRetrace(void)
998 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
999 if(XGIfb_bridgeisslave()) {
1000 return(XGIfbcheckvretracecrt1());
1002 return(XGIfbcheckvretracecrt2());
1005 return(XGIfbcheckvretracecrt1());
1008 /* ----------- FBDev related routines for all series ----------- */
1011 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1013 switch(var->bits_per_pixel) {
1015 var->red.offset = var->green.offset = var->blue.offset = 0;
1016 var->red.length = var->green.length = var->blue.length = 6;
1017 xgi_video_info.video_cmap_len = 256;
1020 var->red.offset = 11;
1021 var->red.length = 5;
1022 var->green.offset = 5;
1023 var->green.length = 6;
1024 var->blue.offset = 0;
1025 var->blue.length = 5;
1026 var->transp.offset = 0;
1027 var->transp.length = 0;
1028 xgi_video_info.video_cmap_len = 16;
1031 var->red.offset = 16;
1032 var->red.length = 8;
1033 var->green.offset = 8;
1034 var->green.length = 8;
1035 var->blue.offset = 0;
1036 var->blue.length = 8;
1037 var->transp.offset = 24;
1038 var->transp.length = 8;
1039 xgi_video_info.video_cmap_len = 16;
1046 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1047 struct fb_info *info)
1050 unsigned int htotal = var->left_margin + var->xres +
1051 var->right_margin + var->hsync_len;
1052 unsigned int vtotal = var->upper_margin + var->yres +
1053 var->lower_margin + var->vsync_len;
1054 #if defined(__powerpc__)
1055 u8 sr_data, cr_data;
1057 unsigned int drate = 0, hrate = 0;
1060 // unsigned char reg,reg1;
1062 DEBUGPRN("Inside do_set_var");
1063 // 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);
1065 info->var.xres_virtual = var->xres_virtual;
1066 info->var.yres_virtual = var->yres_virtual;
1067 info->var.bits_per_pixel = var->bits_per_pixel;
1069 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1071 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1073 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1079 if(!htotal || !vtotal) {
1080 DPRINTK("XGIfb: Invalid 'var' information\n");
1083 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1084 var->pixclock,htotal,vtotal);
1088 if(var->pixclock && htotal && vtotal) {
1089 drate = 1000000000 / var->pixclock;
1090 hrate = (drate * 1000) / htotal;
1091 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1093 xgi_video_info.refresh_rate = 60;
1096 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1097 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1099 old_mode = xgifb_mode_idx;
1102 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1103 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1104 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1105 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1106 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1107 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1115 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1117 xgifb_mode_idx = -1;
1119 if(xgifb_mode_idx < 0) {
1120 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1121 var->yres, var->bits_per_pixel);
1122 xgifb_mode_idx = old_mode;
1126 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1127 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1128 xgi_video_info.refresh_rate = 60;
1134 XGIfb_pre_setmode();
1135 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1136 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1139 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1141 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1143 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1144 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1146 XGIfb_post_setmode();
1148 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1149 XGIbios_mode[xgifb_mode_idx].xres,
1150 XGIbios_mode[xgifb_mode_idx].yres,
1151 XGIbios_mode[xgifb_mode_idx].bpp,
1152 xgi_video_info.refresh_rate);
1154 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1155 xgi_video_info.video_vwidth = info->var.xres_virtual;
1156 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1157 xgi_video_info.video_vheight = info->var.yres_virtual;
1158 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1159 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1160 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1161 xgi_video_info.accel = 0;
1163 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1165 switch(xgi_video_info.video_bpp)
1168 xgi_video_info.DstColor = 0x0000;
1169 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1170 xgi_video_info.video_cmap_len = 256;
1171 #if defined(__powerpc__)
1172 inXGIIDXREG (XGICR, 0x4D, cr_data);
1173 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1177 xgi_video_info.DstColor = 0x8000;
1178 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1179 #if defined(__powerpc__)
1180 inXGIIDXREG (XGICR, 0x4D, cr_data);
1181 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1183 xgi_video_info.video_cmap_len = 16;
1186 xgi_video_info.DstColor = 0xC000;
1187 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1188 xgi_video_info.video_cmap_len = 16;
1189 #if defined(__powerpc__)
1190 inXGIIDXREG (XGICR, 0x4D, cr_data);
1191 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1195 xgi_video_info.video_cmap_len = 16;
1196 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1197 xgi_video_info.accel = 0;
1201 XGIfb_bpp_to_var(var); /*update ARGB info*/
1202 DEBUGPRN("End of do_set_var");
1209 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1213 // printk("Inside pan_var");
1215 if (var->xoffset > (var->xres_virtual - var->xres)) {
1216 // printk( "Pan: xo: %d xv %d xr %d\n",
1217 // var->xoffset, var->xres_virtual, var->xres);
1220 if(var->yoffset > (var->yres_virtual - var->yres)) {
1221 // printk( "Pan: yo: %d yv %d yr %d\n",
1222 // var->yoffset, var->yres_virtual, var->yres);
1225 base = var->yoffset * var->xres_virtual + var->xoffset;
1227 /* calculate base bpp dep. */
1228 switch(var->bits_per_pixel) {
1240 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1242 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1243 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1244 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1245 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1246 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1248 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1249 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1250 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1251 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1252 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1253 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1255 // printk("End of pan_var");
1261 void XGI_dispinfo(struct ap_data *rec)
1263 rec->minfo.bpp = xgi_video_info.video_bpp;
1264 rec->minfo.xres = xgi_video_info.video_width;
1265 rec->minfo.yres = xgi_video_info.video_height;
1266 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1267 rec->minfo.v_yres = xgi_video_info.video_vheight;
1268 rec->minfo.org_x = xgi_video_info.org_x;
1269 rec->minfo.org_y = xgi_video_info.org_y;
1270 rec->minfo.vrate = xgi_video_info.refresh_rate;
1271 rec->iobase = xgi_video_info.vga_base - 0x30;
1272 rec->mem_size = xgi_video_info.video_size;
1273 rec->disp_state = xgi_video_info.disp_state;
1274 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1275 rec->hasVB = xgi_video_info.hasVB;
1276 rec->TV_type = xgi_video_info.TV_type;
1277 rec->TV_plug = xgi_video_info.TV_plug;
1278 rec->chip = xgi_video_info.chip;
1284 static int XGIfb_open(struct fb_info *info, int user)
1289 static int XGIfb_release(struct fb_info *info, int user)
1294 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1298 switch(var->bits_per_pixel) {
1312 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1313 unsigned transp, struct fb_info *info)
1315 if (regno >= XGIfb_get_cmap_len(&info->var))
1318 switch (info->var.bits_per_pixel) {
1320 outXGIREG(XGIDACA, regno);
1321 outXGIREG(XGIDACD, (red >> 10));
1322 outXGIREG(XGIDACD, (green >> 10));
1323 outXGIREG(XGIDACD, (blue >> 10));
1324 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1325 outXGIREG(XGIDAC2A, regno);
1326 outXGIREG(XGIDAC2D, (red >> 8));
1327 outXGIREG(XGIDAC2D, (green >> 8));
1328 outXGIREG(XGIDAC2D, (blue >> 8));
1332 ((u32 *)(info->pseudo_palette))[regno] =
1333 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1339 ((u32 *) (info->pseudo_palette))[regno] =
1340 (red << 16) | (green << 8) | (blue);
1346 static int XGIfb_set_par(struct fb_info *info)
1350 // printk("XGIfb: inside set_par\n");
1351 if((err = XGIfb_do_set_var(&info->var, 1, info)))
1353 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1354 XGIfb_get_fix(&info->fix, info->currcon, info);
1356 XGIfb_get_fix(&info->fix, -1, info);
1358 // printk("XGIfb:end of set_par\n");
1362 static int XGIfb_check_var(struct fb_var_screeninfo *var,
1363 struct fb_info *info)
1365 unsigned int htotal =
1366 var->left_margin + var->xres + var->right_margin +
1368 unsigned int vtotal = 0;
1369 unsigned int drate = 0, hrate = 0;
1371 int refresh_rate, search_idx;
1373 DEBUGPRN("Inside check_var");
1375 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1376 vtotal = var->upper_margin + var->yres + var->lower_margin +
1379 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1380 vtotal = var->upper_margin + var->yres + var->lower_margin +
1383 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1384 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1386 } else vtotal = var->upper_margin + var->yres + var->lower_margin +
1389 if(!(htotal) || !(vtotal)) {
1390 XGIFAIL("XGIfb: no valid timing data");
1394 if(var->pixclock && htotal && vtotal) {
1395 drate = 1000000000 / var->pixclock;
1396 hrate = (drate * 1000) / htotal;
1397 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1399 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1400 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1401 __func__,var->pixclock, htotal, vtotal,
1402 __func__, drate, hrate, xgi_video_info.refresh_rate);
1404 xgi_video_info.refresh_rate = 60;
1408 if((var->pixclock) && (htotal)) {
1409 drate = 1E12 / var->pixclock;
1410 hrate = drate / htotal;
1411 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1412 } else refresh_rate = 60;
1414 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1415 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1418 while((XGIbios_mode[search_idx].mode_no != 0) &&
1419 (XGIbios_mode[search_idx].xres <= var->xres) ) {
1420 if((XGIbios_mode[search_idx].xres == var->xres) &&
1421 (XGIbios_mode[search_idx].yres == var->yres) &&
1422 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1423 if(XGIfb_validate_mode(search_idx) > 0) {
1433 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1434 var->xres, var->yres, var->bits_per_pixel);
1437 while(XGIbios_mode[search_idx].mode_no != 0) {
1439 if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1440 (var->yres <= XGIbios_mode[search_idx].yres) &&
1441 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1442 if(XGIfb_validate_mode(search_idx) > 0) {
1450 var->xres = XGIbios_mode[search_idx].xres;
1451 var->yres = XGIbios_mode[search_idx].yres;
1452 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1453 var->xres, var->yres, var->bits_per_pixel);
1456 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1457 var->xres, var->yres, var->bits_per_pixel);
1462 /* TW: TODO: Check the refresh rate */
1464 /* Adapt RGB settings */
1465 XGIfb_bpp_to_var(var);
1467 /* Sanity check for offsets */
1468 if (var->xoffset < 0)
1470 if (var->yoffset < 0)
1475 if(var->xres != var->xres_virtual)
1476 var->xres_virtual = var->xres;
1477 if(var->yres != var->yres_virtual)
1478 var->yres_virtual = var->yres;
1480 // TW: Now patch yres_virtual if we use panning
1482 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1483 if(var->yres_virtual <= var->yres) {
1484 // TW: Paranoia check
1485 var->yres_virtual = var->yres;
1489 /* Truncate offsets to maximum if too high */
1490 if (var->xoffset > var->xres_virtual - var->xres)
1491 var->xoffset = var->xres_virtual - var->xres - 1;
1493 if (var->yoffset > var->yres_virtual - var->yres)
1494 var->yoffset = var->yres_virtual - var->yres - 1;
1496 /* Set everything else to 0 */
1497 var->red.msb_right =
1498 var->green.msb_right =
1499 var->blue.msb_right =
1500 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1502 DEBUGPRN("end of check_var");
1507 static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1508 struct fb_info* info)
1512 // printk("\nInside pan_display:");
1514 if (var->xoffset > (var->xres_virtual - var->xres))
1516 if (var->yoffset > (var->yres_virtual - var->yres))
1519 if (var->vmode & FB_VMODE_YWRAP) {
1520 if (var->yoffset < 0
1521 || var->yoffset >= info->var.yres_virtual
1522 || var->xoffset) return -EINVAL;
1524 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1525 var->yoffset + info->var.yres > info->var.yres_virtual)
1529 if((err = XGIfb_pan_var(var)) < 0) return err;
1531 info->var.xoffset = var->xoffset;
1532 info->var.yoffset = var->yoffset;
1533 if (var->vmode & FB_VMODE_YWRAP)
1534 info->var.vmode |= FB_VMODE_YWRAP;
1536 info->var.vmode &= ~FB_VMODE_YWRAP;
1538 // printk(" End of pan_display");
1544 static int XGIfb_mmap(struct fb_info *info, struct file *file,
1545 struct vm_area_struct *vma)
1547 unsigned long start;
1551 DEBUGPRN("inside mmap");
1552 if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
1554 off = vma->vm_pgoff << PAGE_SHIFT;
1556 start = (unsigned long) xgi_video_info.video_base;
1557 len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size);
1563 /* By Jake Page: Treat mmap request with offset beyond heapstart
1564 * as request for mapping the mmio area
1567 mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart);
1568 if(off >= mmio_off) {
1570 if(info->var.accel_flags) return -EINVAL;
1572 start = (unsigned long) xgi_video_info.mmio_base;
1573 len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size);
1577 if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL;
1580 vma->vm_pgoff = off >> PAGE_SHIFT;
1581 vma->vm_flags |= VM_IO; /* by Jake Page; is that really needed? */
1583 #if defined(__i386__) || defined(__x86_64__)
1584 if (boot_cpu_data.x86 > 3)
1585 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
1587 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
1591 DEBUGPRN("end of mmap");
1595 static int XGIfb_blank(int blank, struct fb_info *info)
1599 inXGIIDXREG(XGICR, 0x17, reg);
1606 outXGIIDXREG(XGICR, 0x17, reg);
1607 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1608 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1613 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1614 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1617 static int XGIfb_ioctl(struct inode *inode, struct file *file,
1618 unsigned int cmd, unsigned long arg,
1619 struct fb_info *info)
1623 DEBUGPRN("inside ioctl");
1626 if (!capable(CAP_SYS_RAWIO))
1628 XGI_malloc((struct XGI_memreq *) arg);
1631 if (!capable(CAP_SYS_RAWIO))
1633 XGI_free(*(unsigned long *) arg);
1635 case FBIOGET_HWCINFO:
1637 unsigned long *hwc_offset = (unsigned long *) arg;
1639 if (XGIfb_caps & HW_CURSOR_CAP)
1640 *hwc_offset = XGIfb_hwcursor_vbase -
1641 (unsigned long) xgi_video_info.video_vbase;
1647 case FBIOPUT_MODEINFO:
1649 struct mode_info *x = (struct mode_info *)arg;
1651 xgi_video_info.video_bpp = x->bpp;
1652 xgi_video_info.video_width = x->xres;
1653 xgi_video_info.video_height = x->yres;
1654 xgi_video_info.video_vwidth = x->v_xres;
1655 xgi_video_info.video_vheight = x->v_yres;
1656 xgi_video_info.org_x = x->org_x;
1657 xgi_video_info.org_y = x->org_y;
1658 xgi_video_info.refresh_rate = x->vrate;
1659 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1660 switch(xgi_video_info.video_bpp) {
1662 xgi_video_info.DstColor = 0x0000;
1663 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1664 xgi_video_info.video_cmap_len = 256;
1667 xgi_video_info.DstColor = 0x8000;
1668 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1669 xgi_video_info.video_cmap_len = 16;
1672 xgi_video_info.DstColor = 0xC000;
1673 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1674 xgi_video_info.video_cmap_len = 16;
1677 xgi_video_info.video_cmap_len = 16;
1678 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1679 xgi_video_info.accel = 0;
1685 case FBIOGET_DISPINFO:
1686 XGI_dispinfo((struct ap_data *)arg);
1688 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1690 XGIfb_info *x = (XGIfb_info *)arg;
1692 //x->XGIfb_id = XGIFB_ID;
1693 x->XGIfb_version = VER_MAJOR;
1694 x->XGIfb_revision = VER_MINOR;
1695 x->XGIfb_patchlevel = VER_LEVEL;
1696 x->chip_id = xgi_video_info.chip_id;
1697 x->memory = xgi_video_info.video_size / 1024;
1698 x->heapstart = xgi_video_info.heapstart / 1024;
1699 x->fbvidmode = XGIfb_mode_no;
1700 x->XGIfb_caps = XGIfb_caps;
1701 x->XGIfb_tqlen = 512; /* yet unused */
1702 x->XGIfb_pcibus = xgi_video_info.pcibus;
1703 x->XGIfb_pcislot = xgi_video_info.pcislot;
1704 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1705 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1706 x->XGIfb_lcda = XGIfb_detectedlcda;
1709 case XGIFB_GET_VBRSTATUS:
1711 unsigned long *vbrstatus = (unsigned long *) arg;
1712 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1713 else *vbrstatus = 0;
1718 DEBUGPRN("end of ioctl");
1725 /* ----------- FBDev related routines for all series ---------- */
1727 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1728 struct fb_info *info)
1730 DEBUGPRN("inside get_fix");
1731 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1733 strcpy(fix->id, myid);
1735 fix->smem_start = xgi_video_info.video_base;
1737 fix->smem_len = xgi_video_info.video_size;
1740 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1741 if (xgi_video_info.video_size > 0x1000000) {
1742 fix->smem_len = 0xD00000;
1743 } else if (xgi_video_info.video_size > 0x800000)
1744 fix->smem_len = 0x800000;
1746 fix->smem_len = 0x400000;
1748 fix->smem_len = XGIfb_mem * 1024;
1750 fix->type = video_type;
1752 if(xgi_video_info.video_bpp == 8)
1753 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1755 fix->visual = FB_VISUAL_DIRECTCOLOR;
1758 if(XGIfb_ypan) fix->ypanstep = 1;
1761 fix->line_length = xgi_video_info.video_linelength;
1762 fix->mmio_start = xgi_video_info.mmio_base;
1763 fix->mmio_len = XGIfb_mmio_size;
1764 if(xgi_video_info.chip >= XG40)
1765 fix->accel = FB_ACCEL_XGI_XABRE;
1767 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1770 DEBUGPRN("end of get_fix");
1775 static struct fb_ops XGIfb_ops = {
1776 .owner = THIS_MODULE,
1777 .fb_open = XGIfb_open,
1778 .fb_release = XGIfb_release,
1779 .fb_check_var = XGIfb_check_var,
1780 .fb_set_par = XGIfb_set_par,
1781 .fb_setcolreg = XGIfb_setcolreg,
1783 .fb_pan_display = XGIfb_pan_display,
1785 .fb_blank = XGIfb_blank,
1786 .fb_fillrect = fbcon_XGI_fillrect,
1787 .fb_copyarea = fbcon_XGI_copyarea,
1788 .fb_imageblit = cfb_imageblit,
1789 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
1790 .fb_cursor = soft_cursor,
1792 .fb_sync = fbcon_XGI_sync,
1793 .fb_ioctl = XGIfb_ioctl,
1794 // .fb_mmap = XGIfb_mmap,
1797 /* ---------------- Chip generation dependent routines ---------------- */
1800 /* for XGI 315/550/650/740/330 */
1802 static int XGIfb_get_dram_size(void)
1808 /* xorg driver sets 32MB * 1 channel */
1809 if (xgi_video_info.chip == XG27)
1810 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1812 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1813 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1814 case XGI_DRAM_SIZE_1MB:
1815 xgi_video_info.video_size = 0x100000;
1817 case XGI_DRAM_SIZE_2MB:
1818 xgi_video_info.video_size = 0x200000;
1820 case XGI_DRAM_SIZE_4MB:
1821 xgi_video_info.video_size = 0x400000;
1823 case XGI_DRAM_SIZE_8MB:
1824 xgi_video_info.video_size = 0x800000;
1826 case XGI_DRAM_SIZE_16MB:
1827 xgi_video_info.video_size = 0x1000000;
1829 case XGI_DRAM_SIZE_32MB:
1830 xgi_video_info.video_size = 0x2000000;
1832 case XGI_DRAM_SIZE_64MB:
1833 xgi_video_info.video_size = 0x4000000;
1835 case XGI_DRAM_SIZE_128MB:
1836 xgi_video_info.video_size = 0x8000000;
1838 case XGI_DRAM_SIZE_256MB:
1839 xgi_video_info.video_size = 0x10000000;
1845 tmp = (reg & 0x0c) >> 2;
1846 switch(xgi_video_info.chip)
1887 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1888 //PLiad fixed for benchmarking and fb set
1889 //xgi_video_info.video_size = 0x200000;//1024x768x16
1890 //xgi_video_info.video_size = 0x1000000;//benchmark
1892 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1897 static void XGIfb_detect_VB(void)
1901 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1903 switch(xgi_video_info.hasVB) {
1904 case HASVB_LVDS_CHRONTEL:
1905 case HASVB_CHRONTEL:
1909 // XGI_Sense30x(); //Yi-Lin TV Sense?
1913 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1915 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1924 if (XGIfb_crt2type != -1)
1925 /* TW: Override with option */
1926 xgi_video_info.disp_state = XGIfb_crt2type;
1927 else if (cr32 & XGI_VB_TV)
1928 xgi_video_info.disp_state = DISPTYPE_TV;
1929 else if (cr32 & XGI_VB_LCD)
1930 xgi_video_info.disp_state = DISPTYPE_LCD;
1931 else if (cr32 & XGI_VB_CRT2)
1932 xgi_video_info.disp_state = DISPTYPE_CRT2;
1934 xgi_video_info.disp_state = 0;
1936 if(XGIfb_tvplug != -1)
1937 /* PR/TW: Override with option */
1938 xgi_video_info.TV_plug = XGIfb_tvplug;
1939 else if (cr32 & XGI_VB_HIVISION) {
1940 xgi_video_info.TV_type = TVMODE_HIVISION;
1941 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1943 else if (cr32 & XGI_VB_SVIDEO)
1944 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1945 else if (cr32 & XGI_VB_COMPOSITE)
1946 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1947 else if (cr32 & XGI_VB_SCART)
1948 xgi_video_info.TV_plug = TVPLUG_SCART;
1950 if(xgi_video_info.TV_type == 0) {
1951 /* TW: PAL/NTSC changed for 650 */
1952 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1954 inXGIIDXREG(XGICR, 0x38, temp);
1956 xgi_video_info.TV_type = TVMODE_PAL;
1958 xgi_video_info.TV_type = TVMODE_NTSC;
1962 inXGIIDXREG(XGICR, 0x79, temp);
1964 xgi_video_info.TV_type = TVMODE_PAL;
1966 xgi_video_info.TV_type = TVMODE_NTSC;
1970 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1971 if (XGIfb_forcecrt1 != -1) {
1972 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1973 else XGIfb_crt1off = 1;
1977 static void XGIfb_get_VB_type(void)
1981 if (!XGIfb_has_VB()) {
1982 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1983 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1984 case XGI310_EXTERNAL_CHIP_LVDS:
1985 xgi_video_info.hasVB = HASVB_LVDS;
1987 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1988 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1997 static int XGIfb_has_VB(void)
2001 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
2002 switch (vb_chipid) {
2004 xgi_video_info.hasVB = HASVB_301;
2007 xgi_video_info.hasVB = HASVB_302;
2010 xgi_video_info.hasVB = HASVB_NONE;
2018 /* ------------------ Sensing routines ------------------ */
2020 /* TW: Determine and detect attached devices on XGI30x */
2022 XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
2026 outXGIIDXREG(XGIPART4,0x11,tempbl);
2027 temp = tempbh | tempcl;
2028 setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
2029 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
2031 inXGIIDXREG(XGIPART4,0x03,temp);
2041 u8 testsvhs_tempbl, testsvhs_tempbh;
2042 u8 testsvhs_tempcl, testsvhs_tempch;
2043 u8 testcvbs_tempbl, testcvbs_tempbh;
2044 u8 testcvbs_tempcl, testcvbs_tempch;
2045 u8 testvga2_tempbl, testvga2_tempbh;
2046 u8 testvga2_tempcl, testvga2_tempch;
2049 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2050 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
2054 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
2055 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
2056 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
2057 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
2058 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
2059 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
2060 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
2061 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
2062 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
2063 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2064 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2065 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
2066 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
2069 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
2070 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
2071 inXGIIDXREG(XGIPART4,0x01,myflag);
2073 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
2074 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
2075 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2078 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2079 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2080 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2081 testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2082 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2083 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2085 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2086 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2087 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2091 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2092 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2093 testvga2_tempcl, testvga2_tempch);
2095 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2096 orXGIIDXREG(XGICR, 0x32, 0x10);
2100 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2101 testsvhs_tempcl, testsvhs_tempch);
2103 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2104 /* TW: So we can be sure that there IS a SVHS output */
2105 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2106 orXGIIDXREG(XGICR, 0x32, 0x02);
2110 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2111 testcvbs_tempcl, testcvbs_tempch);
2113 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2114 /* TW: So we can be sure that there IS a CVBS output */
2115 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2116 orXGIIDXREG(XGICR, 0x32, 0x01);
2119 XGIDoSense(0, 0, 0, 0);
2121 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2126 /* ------------------------ Heap routines -------------------------- */
2128 static int XGIfb_heap_init(void)
2133 int agp_enabled = 1;
2135 unsigned long *cmdq_baseport = 0;
2136 unsigned long *read_port = 0;
2137 unsigned long *write_port = 0;
2138 XGI_CMDTYPE cmd_type;
2140 struct agp_kern_info *agp_info;
2141 struct agp_memory *agp;
2145 /* TW: The heap start is either set manually using the "mem" parameter, or
2146 * defaults as follows:
2147 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2148 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2149 * -) If 4MB or less is available, let it start at 4MB.
2150 * This is for avoiding a clash with X driver which uses the beginning
2151 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2153 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2154 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2156 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2157 if (xgi_video_info.video_size > 0x1000000) {
2158 xgi_video_info.heapstart = 0xD00000;
2159 } else if (xgi_video_info.video_size > 0x800000) {
2160 xgi_video_info.heapstart = 0x800000;
2162 xgi_video_info.heapstart = 0x400000;
2165 xgi_video_info.heapstart = XGIfb_mem * 1024;
2168 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2169 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2170 (int)(xgi_video_info.heapstart / 1024));
2172 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2173 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2177 /* TW: Now initialize the 310 series' command queue mode.
2178 * On 310/325, there are three queue modes available which
2179 * are chosen by setting bits 7:5 in SR26:
2180 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2181 * track of the queue, the FIFO, command parsing and so
2182 * on. This is the one comparable to the 300 series.
2183 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2184 * have to do queue management himself. Register 0x85c4 will
2185 * hold the location of the next free queue slot, 0x85c8
2186 * is the "queue read pointer" whose way of working is
2187 * unknown to me. Anyway, this mode would require a
2188 * translation of the MMIO commands to some kind of
2189 * accelerator assembly and writing these commands
2190 * to the memory location pointed to by 0x85c4.
2191 * We will not use this, as nobody knows how this
2192 * "assembly" works, and as it would require a complete
2193 * re-write of the accelerator code.
2194 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2195 * queue in AGP memory space.
2197 * SR26 bit 4 is called "Bypass H/W queue".
2198 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2199 * SR26 bit 0 resets the queue
2200 * Size of queue memory is encoded in bits 3:2 like this:
2205 * The queue location is to be written to 0x85C0.
2208 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2209 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2210 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2212 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2214 agp_size = COMMAND_QUEUE_AREA_SIZE;
2217 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2218 agp_info = vmalloc(sizeof(*agp_info));
2219 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2220 agp_copy_info(agp_info);
2222 agp_backend_acquire();
2224 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2227 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2230 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2231 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2232 /* TODO: Free AGP memory here */
2243 /* TW: Now select the queue mode */
2245 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2246 cmd_type = AGP_CMD_QUEUE;
2247 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2248 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2249 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2250 cmd_type = VM_CMD_QUEUE;
2251 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2253 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2254 cmd_type = MMIO_CMD;
2259 temp = XGI_CMD_QUEUE_SIZE_512k;
2262 temp = XGI_CMD_QUEUE_SIZE_1M;
2265 temp = XGI_CMD_QUEUE_SIZE_2M;
2268 temp = XGI_CMD_QUEUE_SIZE_4M;
2275 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2276 agp_info->aper_base, agp->physical, agp_size/1024);
2278 agp_phys = agp_info->aper_base + agp->physical;
2280 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2281 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2283 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2285 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2287 *write_port = *read_port;
2289 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2290 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2292 *cmdq_baseport = agp_phys;
2294 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2299 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2300 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2302 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2304 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2306 *write_port = *read_port;
2308 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2309 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2311 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2313 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2315 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2316 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2321 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2322 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2323 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2324 * enough. Reserve memory in any way.
2326 // FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2327 // FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2329 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2330 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2332 // FIXME *write_port = *read_port;
2334 // FIXME /* TW: Set Auto_Correction bit */
2335 // FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2336 // FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2338 // FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2340 // FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2342 // FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2343 // FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2350 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2351 top of the videoRAM, right below the TB memory area (if used). */
2352 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2353 XGIfb_heap_end -= XGIfb_hwcursor_size;
2354 XGIfb_heap_size -= XGIfb_hwcursor_size;
2355 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2357 XGIfb_caps |= HW_CURSOR_CAP;
2359 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2360 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2363 XGIfb_heap.poha_chain = NULL;
2364 XGIfb_heap.poh_freelist = NULL;
2366 poh = XGIfb_poh_new_node();
2368 if(poh == NULL) return 1;
2370 poh->poh_next = &XGIfb_heap.oh_free;
2371 poh->poh_prev = &XGIfb_heap.oh_free;
2372 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2373 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2375 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2376 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2377 (unsigned int) poh->size / 1024);
2379 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2380 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2382 XGIfb_heap.oh_free.poh_next = poh;
2383 XGIfb_heap.oh_free.poh_prev = poh;
2384 XGIfb_heap.oh_free.size = 0;
2385 XGIfb_heap.max_freesize = poh->size;
2387 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2388 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2389 XGIfb_heap.oh_used.size = SENTINEL;
2394 static XGI_OH *XGIfb_poh_new_node(void)
2401 if (XGIfb_heap.poh_freelist == NULL) {
2402 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2403 if(!poha) return NULL;
2405 poha->poha_next = XGIfb_heap.poha_chain;
2406 XGIfb_heap.poha_chain = poha;
2408 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2410 poh = &poha->aoh[0];
2411 for (i = cOhs - 1; i != 0; i--) {
2412 poh->poh_next = poh + 1;
2416 poh->poh_next = NULL;
2417 XGIfb_heap.poh_freelist = &poha->aoh[0];
2420 poh = XGIfb_heap.poh_freelist;
2421 XGIfb_heap.poh_freelist = poh->poh_next;
2426 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2432 if (size > XGIfb_heap.max_freesize) {
2433 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2434 (unsigned int) size / 1024);
2438 pohThis = XGIfb_heap.oh_free.poh_next;
2440 while (pohThis != &XGIfb_heap.oh_free) {
2441 if (size <= pohThis->size) {
2445 pohThis = pohThis->poh_next;
2449 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2450 (unsigned int) size / 1024);
2454 if (size == pohThis->size) {
2456 XGIfb_delete_node(pohThis);
2458 pohRoot = XGIfb_poh_new_node();
2460 if (pohRoot == NULL) {
2464 pohRoot->offset = pohThis->offset;
2465 pohRoot->size = size;
2467 pohThis->offset += size;
2468 pohThis->size -= size;
2471 XGIfb_heap.max_freesize -= size;
2473 pohThis = &XGIfb_heap.oh_used;
2474 XGIfb_insert_node(pohThis, pohRoot);
2479 static void XGIfb_delete_node(XGI_OH *poh)
2484 poh_prev = poh->poh_prev;
2485 poh_next = poh->poh_next;
2487 poh_prev->poh_next = poh_next;
2488 poh_next->poh_prev = poh_prev;
2492 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2496 pohTemp = pohList->poh_next;
2498 pohList->poh_next = poh;
2499 pohTemp->poh_prev = poh;
2501 poh->poh_prev = pohList;
2502 poh->poh_next = pohTemp;
2505 static XGI_OH *XGIfb_poh_free(unsigned long base)
2511 unsigned long ulUpper;
2512 unsigned long ulLower;
2515 poh_freed = XGIfb_heap.oh_used.poh_next;
2517 while(poh_freed != &XGIfb_heap.oh_used) {
2518 if(poh_freed->offset == base) {
2523 poh_freed = poh_freed->poh_next;
2526 if (!foundNode) return (NULL);
2528 XGIfb_heap.max_freesize += poh_freed->size;
2530 poh_prev = poh_next = NULL;
2531 ulUpper = poh_freed->offset + poh_freed->size;
2532 ulLower = poh_freed->offset;
2534 pohThis = XGIfb_heap.oh_free.poh_next;
2536 while (pohThis != &XGIfb_heap.oh_free) {
2537 if (pohThis->offset == ulUpper) {
2540 else if ((pohThis->offset + pohThis->size) ==
2544 pohThis = pohThis->poh_next;
2547 XGIfb_delete_node(poh_freed);
2549 if (poh_prev && poh_next) {
2550 poh_prev->size += (poh_freed->size + poh_next->size);
2551 XGIfb_delete_node(poh_next);
2552 XGIfb_free_node(poh_freed);
2553 XGIfb_free_node(poh_next);
2558 poh_prev->size += poh_freed->size;
2559 XGIfb_free_node(poh_freed);
2564 poh_next->size += poh_freed->size;
2565 poh_next->offset = poh_freed->offset;
2566 XGIfb_free_node(poh_freed);
2570 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2575 static void XGIfb_free_node(XGI_OH *poh)
2577 if(poh == NULL) return;
2579 poh->poh_next = XGIfb_heap.poh_freelist;
2580 XGIfb_heap.poh_freelist = poh;
2584 void XGI_malloc(struct XGI_memreq *req)
2588 poh = XGIfb_poh_allocate(req->size);
2593 DPRINTK("XGIfb: Video RAM allocation failed\n");
2595 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2596 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2598 req->offset = poh->offset;
2599 req->size = poh->size;
2604 void XGI_free(unsigned long base)
2608 poh = XGIfb_poh_free(base);
2611 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2612 (unsigned int) base);
2616 /* --------------------- SetMode routines ------------------------- */
2618 static void XGIfb_pre_setmode(void)
2620 u8 cr30 = 0, cr31 = 0;
2622 inXGIIDXREG(XGICR, 0x31, cr31);
2625 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2627 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2628 cr31 |= XGI_DRIVER_MODE;
2631 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2632 cr31 |= XGI_DRIVER_MODE;
2635 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2636 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2637 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2638 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2639 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2640 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2641 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2642 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2643 cr31 |= XGI_DRIVER_MODE;
2645 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2650 default: /* disable CRT2 */
2652 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2655 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2656 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2657 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2659 if(xgi_video_info.accel) XGIfb_syncaccel();
2664 static void XGIfb_post_setmode(void)
2667 BOOLEAN doit = TRUE;
2668 #if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */
2669 /* Backup mode number to MMIO space */
2670 if(xgi_video_info.mmio_vbase) {
2671 *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no;
2674 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2675 outXGIIDXREG(XGICR,0x13,0x00);
2676 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2678 if (xgi_video_info.video_bpp == 8) {
2679 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2680 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2683 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2684 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2689 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2690 if(xgi_video_info.hasVB != HASVB_NONE) {
2691 inXGIIDXREG(XGIPART1, 0x00, reg);
2694 if((reg & 0x50) == 0x10) {
2698 } else XGIfb_crt1off = 0;
2700 inXGIIDXREG(XGICR, 0x17, reg);
2701 if((XGIfb_crt1off) && (doit))
2705 outXGIIDXREG(XGICR, 0x17, reg);
2707 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2709 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2711 inXGIIDXREG(XGIPART4, 0x01, reg);
2713 if(reg < 0xB0) { /* Set filter for XGI301 */
2715 switch (xgi_video_info.video_width) {
2717 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2720 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2723 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2726 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2733 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2735 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2737 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2739 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2741 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2743 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2745 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2747 switch (xgi_video_info.video_width) {
2749 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2750 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2751 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2752 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2755 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2756 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2757 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2758 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2761 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2762 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2763 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2764 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2769 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2771 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2773 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2775 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2777 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2779 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2781 switch (xgi_video_info.video_width) {
2783 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2784 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2785 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2786 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2789 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2790 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2791 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2792 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2795 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2796 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2797 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2798 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2804 if ((filter >= 0) && (filter <=7)) {
2805 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2806 XGI_TV_filter[filter_tb].filter[filter][0],
2807 XGI_TV_filter[filter_tb].filter[filter][1],
2808 XGI_TV_filter[filter_tb].filter[filter][2],
2809 XGI_TV_filter[filter_tb].filter[filter][3]
2811 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2812 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2813 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2814 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2824 XGIINITSTATIC int __init XGIfb_setup(char *options)
2830 xgi_video_info.refresh_rate = 0;
2832 printk(KERN_INFO "XGIfb: Options %s\n", options);
2834 if (!options || !*options)
2837 while((this_opt = strsep(&options, ",")) != NULL) {
2839 if (!*this_opt) continue;
2841 if (!strncmp(this_opt, "mode:", 5)) {
2842 XGIfb_search_mode(this_opt + 5);
2843 } else if (!strncmp(this_opt, "vesa:", 5)) {
2844 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2845 } else if (!strncmp(this_opt, "mode:", 5)) {
2846 XGIfb_search_mode(this_opt + 5);
2847 } else if (!strncmp(this_opt, "vesa:", 5)) {
2848 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2849 } else if (!strncmp(this_opt, "vrate:", 6)) {
2850 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2851 } else if (!strncmp(this_opt, "rate:", 5)) {
2852 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2853 } else if (!strncmp(this_opt, "off", 3)) {
2855 } else if (!strncmp(this_opt, "crt1off", 7)) {
2857 } else if (!strncmp(this_opt, "filter:", 7)) {
2858 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2859 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2860 XGIfb_search_crt2type(this_opt + 14);
2861 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2862 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2863 } else if (!strncmp(this_opt, "tvmode:",7)) {
2864 XGIfb_search_tvstd(this_opt + 7);
2865 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2866 XGIfb_search_tvstd(this_opt + 7);
2867 } else if (!strncmp(this_opt, "mem:",4)) {
2868 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2869 } else if (!strncmp(this_opt, "dstn", 4)) {
2871 /* TW: DSTN overrules forcecrt2type */
2872 XGIfb_crt2type = DISPTYPE_LCD;
2873 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2874 XGIfb_search_queuemode(this_opt + 10);
2875 } else if (!strncmp(this_opt, "pdc:", 4)) {
2876 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2877 if(XGIfb_pdc & ~0x3c) {
2878 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2881 } else if (!strncmp(this_opt, "noaccel", 7)) {
2883 } else if (!strncmp(this_opt, "noypan", 6)) {
2885 } else if (!strncmp(this_opt, "userom:", 7)) {
2886 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2887 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2888 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2890 XGIfb_search_mode(this_opt);
2891 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2894 /* TW: Acceleration only with MMIO mode */
2895 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2899 /* TW: Panning only with acceleration */
2900 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2903 printk("\nxgifb: outa xgifb_setup 3450");
2908 static unsigned char VBIOS_BUF[65535];
2910 unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
2913 u32 rom_address = 0;
2916 /* Get the size of the expansion rom */
2917 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2918 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2919 if ((rom_size & 0x01) == 0)
2925 rom_size &= 0xFFFFF800;
2926 rom_size = (~rom_size)+1;
2928 rom_address = pci_resource_start(dev, 0);
2929 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2931 printk("No suitable rom address found\n"); return NULL;
2934 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2937 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2939 /* memcpy(copy_address, rom_address, rom_size); */
2941 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2943 unsigned char *from = (unsigned char *)virt_addr;
2944 unsigned char *to = (unsigned char *)copy_address;
2945 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2948 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2950 printk("Copy is done\n");
2952 return copy_address;
2955 int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2963 XGIfb_registered = 0;
2965 memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
2966 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
2967 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2968 if(!fb_info) return -ENOMEM;
2970 XGI_fb_info = kmalloc( sizeof(struct fb_info), GFP_KERNEL);
2971 if(!XGI_fb_info) return -ENOMEM;
2972 memset(XGI_fb_info, 0, sizeof(struct fb_info));
2975 xgi_video_info.chip_id = pdev->device;
2976 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2977 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2978 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2979 XGIvga_enabled = reg16 & 0x01;
2981 xgi_video_info.pcibus = pdev->bus->number;
2982 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2983 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2984 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2985 xgi_video_info.subsysdevice = pdev->subsystem_device;
2987 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2988 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2989 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2990 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2991 XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base;
2992 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2993 printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2995 if (pci_enable_device(pdev))
2998 XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
3000 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3001 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
3003 if(reg1 != 0xa1) /*I/O error */
3005 printk("\nXGIfb: I/O error!!!");
3009 switch (xgi_video_info.chip_id) {
3010 case PCI_DEVICE_ID_XG_20:
3011 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
3012 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
3013 if (CR48&GPIOG_READ)
3014 xgi_video_info.chip = XG21;
3016 xgi_video_info.chip = XG20;
3017 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3018 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3020 case PCI_DEVICE_ID_XG_40:
3021 xgi_video_info.chip = XG40;
3022 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3023 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3025 case PCI_DEVICE_ID_XG_41:
3026 xgi_video_info.chip = XG41;
3027 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3028 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3030 case PCI_DEVICE_ID_XG_42:
3031 xgi_video_info.chip = XG42;
3032 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3033 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3035 case PCI_DEVICE_ID_XG_27:
3036 xgi_video_info.chip = XG27;
3037 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3038 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3044 printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
3045 XGIhw_ext.jChipType = xgi_video_info.chip;
3047 switch (xgi_video_info.chip) {
3055 XGIhw_ext.bIntegratedMMEnabled = TRUE;
3063 XGIhw_ext.pDevice = NULL;
3064 if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
3066 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
3068 if(XGIhw_ext.pjVirtualRomBase)
3069 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
3071 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3073 XGIhw_ext.pjVirtualRomBase = NULL;
3074 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3076 XGIhw_ext.pjCustomizedROMImage = NULL;
3077 XGIhw_ext.bSkipDramSizing = 0;
3078 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3079 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
3080 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3083 XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
3084 if (XGIhw_ext.pSR == NULL)
3086 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3089 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3091 XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
3092 if (XGIhw_ext.pCR == NULL)
3094 vfree(XGIhw_ext.pSR);
3095 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3098 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3103 if (!XGIvga_enabled)
3105 /* Mapping Max FB Size for 315 Init */
3106 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3107 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3110 printk("XGIfb: XGIInit() ...");
3111 /* XGIInitNewt for LINUXBIOS only */
3112 if(XGIInitNew(&XGIhw_ext))
3122 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3130 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3131 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3134 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3136 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3137 // Set SR13 ,14 temporarily for UDtech
3138 outXGIIDXREG(XGISR, 0x13, 0x45);
3139 outXGIIDXREG(XGISR, 0x14, 0x51);
3145 if (XGIfb_get_dram_size())
3147 vfree(XGIhw_ext.pSR);
3148 vfree(XGIhw_ext.pCR);
3149 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3155 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3157 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3158 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3159 /* Enable 2D accelerator engine */
3160 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3163 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3165 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3166 { printk("unable request memory size %x",xgi_video_info.video_size);
3167 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3168 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3169 vfree(XGIhw_ext.pSR);
3170 vfree(XGIhw_ext.pCR);
3174 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3176 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3177 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3178 vfree(XGIhw_ext.pSR);
3179 vfree(XGIhw_ext.pCR);
3183 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3184 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3185 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3187 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3188 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3190 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3191 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3192 printk("XGIfb: XGIInitNew() ...");
3193 if(XGIInitNew(&XGIhw_ext))
3202 if(XGIfb_heap_init())
3204 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3208 xgi_video_info.mtrr = (unsigned int) 0;
3210 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3212 xgi_video_info.hasVB = HASVB_NONE;
3213 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3214 xgi_video_info.hasVB = HASVB_NONE;
3215 else if(xgi_video_info.chip == XG21) {
3216 inXGIIDXREG(XGICR,0x38,CR38);
3217 if ((CR38&0xE0) == 0xC0) {
3218 xgi_video_info.disp_state = DISPTYPE_LCD;
3219 if (!XGIfb_GetXG21LVDSData()) {
3221 for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
3222 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3223 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3224 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3229 else if ((CR38&0xE0) == 0x60)
3230 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3232 xgi_video_info.hasVB = HASVB_NONE;
3235 XGIfb_get_VB_type();
3237 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3239 XGIhw_ext.ulExternalChip = 0;
3241 switch (xgi_video_info.hasVB) {
3243 inXGIIDXREG(XGIPART4, 0x01, reg);
3245 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3246 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3247 } else if (reg >= 0xD0) {
3248 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3249 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3251 /* else if (reg >= 0xB0) {
3252 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3253 inXGIIDXREG(XGIPART4,0x23,reg1);
3254 printk("XGIfb: XGI301B bridge detected\n");
3257 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3258 printk("XGIfb: XGI301 bridge detected\n");
3262 inXGIIDXREG(XGIPART4, 0x01, reg);
3264 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3265 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3266 } else if (reg >= 0xD0) {
3267 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3268 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3269 } else if (reg >= 0xB0) {
3270 inXGIIDXREG(XGIPART4,0x23,reg1);
3272 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3275 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3276 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3280 XGIhw_ext.ulExternalChip = 0x1;
3281 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3283 case HASVB_TRUMPION:
3284 XGIhw_ext.ulExternalChip = 0x2;
3285 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3287 case HASVB_CHRONTEL:
3288 XGIhw_ext.ulExternalChip = 0x4;
3289 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3291 case HASVB_LVDS_CHRONTEL:
3292 XGIhw_ext.ulExternalChip = 0x5;
3293 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3296 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3300 if (xgi_video_info.hasVB != HASVB_NONE) {
3304 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3306 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3308 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3310 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3313 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3315 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3317 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3321 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3325 XGIfb_detectedpdc = 0;
3327 XGIfb_detectedlcda = 0xff;
3330 /* TW: Try to find about LCDA */
3332 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3333 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3334 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3337 inXGIIDXREG(XGICR,0x34,tmp);
3340 // Currently on LCDA? (Some BIOSes leave CR38)
3341 inXGIIDXREG(XGICR,0x38,tmp);
3342 if((tmp & 0x03) == 0x03)
3344 // XGI_Pr.XGI_UseLCDA = TRUE;
3347 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3348 inXGIIDXREG(XGICR,0x35,tmp);
3351 // XGI_Pr.XGI_UseLCDA = TRUE;
3354 inXGIIDXREG(XGICR,0x30,tmp);
3357 inXGIIDXREG(XGIPART1,0x13,tmp);
3360 // XGI_Pr.XGI_UseLCDA = TRUE;
3372 if (xgifb_mode_idx >= 0)
3373 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3375 if (xgifb_mode_idx < 0) {
3376 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3378 xgifb_mode_idx = DEFAULT_LCDMODE;
3379 if (xgi_video_info.chip == XG21)
3381 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3385 xgifb_mode_idx = DEFAULT_TVMODE;
3388 xgifb_mode_idx = DEFAULT_MODE;
3393 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3396 if( xgi_video_info.refresh_rate == 0)
3397 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3398 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3400 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3401 xgi_video_info.refresh_rate = 60;
3404 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3405 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3406 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3407 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3408 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3409 switch(xgi_video_info.video_bpp) {
3411 xgi_video_info.DstColor = 0x0000;
3412 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3413 xgi_video_info.video_cmap_len = 256;
3416 xgi_video_info.DstColor = 0x8000;
3417 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3418 xgi_video_info.video_cmap_len = 16;
3421 xgi_video_info.DstColor = 0xC000;
3422 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3423 xgi_video_info.video_cmap_len = 16;
3426 xgi_video_info.video_cmap_len = 16;
3427 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3433 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3434 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3435 xgi_video_info.refresh_rate);
3437 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3438 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3439 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3441 XGIfb_bpp_to_var(&default_var);
3443 default_var.pixclock = (u32) (1000000000 /
3444 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3445 XGIfb_mode_no, XGIfb_rate_idx));
3447 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3448 XGIfb_mode_no, XGIfb_rate_idx,
3449 &default_var.left_margin, &default_var.right_margin,
3450 &default_var.upper_margin, &default_var.lower_margin,
3451 &default_var.hsync_len, &default_var.vsync_len,
3452 &default_var.sync, &default_var.vmode)) {
3454 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3455 default_var.yres <<= 1;
3456 default_var.yres_virtual <<= 1;
3457 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3458 default_var.pixclock >>= 1;
3459 default_var.yres >>= 1;
3460 default_var.yres_virtual >>= 1;
3469 default_var.yres_virtual =
3470 xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
3471 if(default_var.yres_virtual <= default_var.yres) {
3472 default_var.yres_virtual = default_var.yres;
3479 xgi_video_info.accel = 0;
3481 xgi_video_info.accel = -1;
3482 default_var.accel_flags |= FB_ACCELF_TEXT;
3486 fb_info->flags = FBINFO_FLAG_DEFAULT;
3487 fb_info->var = default_var;
3488 fb_info->fix = XGIfb_fix;
3489 fb_info->par = &xgi_video_info;
3490 fb_info->screen_base = xgi_video_info.video_vbase;
3491 fb_info->fbops = &XGIfb_ops;
3492 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3493 fb_info->pseudo_palette = pseudo_palette;
3495 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3499 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3500 (unsigned int) xgi_video_info.video_size,
3501 MTRR_TYPE_WRCOMB, 1);
3502 if(xgi_video_info.mtrr) {
3503 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3507 if(register_framebuffer(fb_info) < 0)
3512 XGIfb_registered = 1;
3514 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO);
3516 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3517 XGIfb_accel ? "enabled" : "disabled",
3518 XGIfb_ypan ? "ypan" : "redraw");
3520 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3521 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3532 /*****************************************************/
3533 /* PCI DEVICE HANDLING */
3534 /*****************************************************/
3536 static void __devexit xgifb_remove(struct pci_dev *pdev)
3538 /* Unregister the framebuffer */
3539 // if(xgi_video_info.registered) {
3540 unregister_framebuffer(fb_info);
3541 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
3542 framebuffer_release(fb_info);
3548 pci_set_drvdata(pdev, NULL);
3552 static struct pci_driver xgifb_driver = {
3554 .id_table = xgifb_pci_table,
3555 .probe = xgifb_probe,
3556 .remove = __devexit_p(xgifb_remove)
3559 XGIINITSTATIC int __init xgifb_init(void)
3561 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
3563 char *option = NULL;
3565 if (fb_get_options("xgifb", &option))
3567 XGIfb_setup(option);
3570 return(pci_register_driver(&xgifb_driver));
3573 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
3575 module_init(xgifb_init);
3579 /*****************************************************/
3581 /*****************************************************/
3585 static char *mode = NULL;
3586 static int vesa = 0;
3587 static unsigned int rate = 0;
3588 static unsigned int crt1off = 1;
3589 static unsigned int mem = 0;
3590 static char *forcecrt2type = NULL;
3591 static int forcecrt1 = -1;
3592 static int pdc = -1;
3593 static int pdc1 = -1;
3594 static int noaccel = -1;
3595 static int noypan = -1;
3596 static int nomax = -1;
3597 static int userom = -1;
3598 static int useoem = -1;
3599 static char *tvstandard = NULL;
3600 static int nocrt2rate = 0;
3601 static int scalelcd = -1;
3602 static char *specialtiming = NULL;
3603 static int lvdshl = -1;
3604 static int tvxposoffset = 0, tvyposoffset = 0;
3605 #if !defined(__i386__) && !defined(__x86_64__)
3606 static int resetcard = 0;
3607 static int videoram = 0;
3610 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3611 MODULE_LICENSE("GPL");
3612 MODULE_AUTHOR("XGITECH , Others");
3616 module_param(mem, int, 0);
3617 module_param(noaccel, int, 0);
3618 module_param(noypan, int, 0);
3619 module_param(nomax, int, 0);
3620 module_param(userom, int, 0);
3621 module_param(useoem, int, 0);
3622 module_param(mode, charp, 0);
3623 module_param(vesa, int, 0);
3624 module_param(rate, int, 0);
3625 module_param(forcecrt1, int, 0);
3626 module_param(forcecrt2type, charp, 0);
3627 module_param(scalelcd, int, 0);
3628 module_param(pdc, int, 0);
3629 module_param(pdc1, int, 0);
3630 module_param(specialtiming, charp, 0);
3631 module_param(lvdshl, int, 0);
3632 module_param(tvstandard, charp, 0);
3633 module_param(tvxposoffset, int, 0);
3634 module_param(tvyposoffset, int, 0);
3635 module_param(filter, int, 0);
3636 module_param(nocrt2rate, int, 0);
3637 #if !defined(__i386__) && !defined(__x86_64__)
3638 module_param(resetcard, int, 0);
3639 module_param(videoram, int, 0);
3643 MODULE_PARM_DESC(mem,
3644 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3645 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3646 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3647 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3648 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3649 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3650 "for XFree86 4.x/X.org 6.7 and later.\n");
3652 MODULE_PARM_DESC(noaccel,
3653 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3656 MODULE_PARM_DESC(noypan,
3657 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3658 "will be performed by redrawing the screen. (default: 0)\n");
3660 MODULE_PARM_DESC(nomax,
3661 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3662 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3663 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3664 "enable the user to positively specify a virtual Y size of the screen using\n"
3665 "fbset. (default: 0)\n");
3669 MODULE_PARM_DESC(mode,
3670 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3671 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3672 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3673 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3675 MODULE_PARM_DESC(vesa,
3676 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3677 "0x117 (default: 0x0103)\n");
3680 MODULE_PARM_DESC(rate,
3681 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3682 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3683 "will be ignored (default: 60)\n");
3685 MODULE_PARM_DESC(forcecrt1,
3686 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3687 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3688 "0=CRT1 OFF) (default: [autodetected])\n");
3690 MODULE_PARM_DESC(forcecrt2type,
3691 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3692 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3693 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3694 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3695 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3696 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3697 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3698 "depends on the very hardware in use. (default: [autodetected])\n");
3700 MODULE_PARM_DESC(scalelcd,
3701 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3702 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3703 "show black bars around the image, TMDS panels will probably do the scaling\n"
3704 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3706 MODULE_PARM_DESC(pdc,
3707 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3708 "should detect this correctly in most cases; however, sometimes this is not\n"
3709 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3710 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3711 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3712 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3714 MODULE_PARM_DESC(pdc1,
3715 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3716 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3717 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3718 "implemented yet.\n");
3720 MODULE_PARM_DESC(specialtiming,
3721 "\nPlease refer to documentation for more information on this option.\n");
3723 MODULE_PARM_DESC(lvdshl,
3724 "\nPlease refer to documentation for more information on this option.\n");
3726 MODULE_PARM_DESC(tvstandard,
3727 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3728 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3730 MODULE_PARM_DESC(tvxposoffset,
3731 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3734 MODULE_PARM_DESC(tvyposoffset,
3735 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3738 MODULE_PARM_DESC(filter,
3739 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3740 "(Possible values 0-7, default: [no filter])\n");
3742 MODULE_PARM_DESC(nocrt2rate,
3743 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3744 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3749 int __init xgifb_init_module(void)
3751 printk("\nXGIfb_init_module");
3753 XGIfb_search_mode(mode);
3754 else if (vesa != -1)
3755 XGIfb_search_vesamode(vesa);
3757 return(xgifb_init());
3760 static void __exit xgifb_remove_module(void)
3762 pci_unregister_driver(&xgifb_driver);
3763 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3766 module_init(xgifb_init_module);
3767 module_exit(xgifb_remove_module);
3769 #endif /* /MODULE */
3771 EXPORT_SYMBOL(XGI_malloc);
3772 EXPORT_SYMBOL(XGI_free);