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>
46 #define Index_CR_GPIO_Reg1 0x48
47 #define Index_CR_GPIO_Reg2 0x49
48 #define Index_CR_GPIO_Reg3 0x4a
50 #define GPIOG_EN (1<<6)
51 #define GPIOG_WRITE (1<<6)
52 #define GPIOG_READ (1<<1)
53 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
55 #define XGIFB_ROM_SIZE 65536
57 /* -------------------- Macro definitions ---------------------------- */
62 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
64 #define DPRINTK(fmt, args...)
68 static void dumpVGAReg(void)
72 outXGIIDXREG(XGISR, 0x05, 0x86);
74 outXGIIDXREG(XGISR, 0x08, 0x4f);
75 outXGIIDXREG(XGISR, 0x0f, 0x20);
76 outXGIIDXREG(XGISR, 0x11, 0x4f);
77 outXGIIDXREG(XGISR, 0x13, 0x45);
78 outXGIIDXREG(XGISR, 0x14, 0x51);
79 outXGIIDXREG(XGISR, 0x1e, 0x41);
80 outXGIIDXREG(XGISR, 0x1f, 0x0);
81 outXGIIDXREG(XGISR, 0x20, 0xa1);
82 outXGIIDXREG(XGISR, 0x22, 0xfb);
83 outXGIIDXREG(XGISR, 0x26, 0x22);
84 outXGIIDXREG(XGISR, 0x3e, 0x07);
87 /* outXGIIDXREG(XGICR, 0x19, 0x00); */
88 /* outXGIIDXREG(XGICR, 0x1a, 0x3C); */
89 /* outXGIIDXREG(XGICR, 0x22, 0xff); */
90 /* outXGIIDXREG(XGICR, 0x3D, 0x10); */
92 /* outXGIIDXREG(XGICR, 0x4a, 0xf3); */
94 /* outXGIIDXREG(XGICR, 0x57, 0x0); */
95 /* outXGIIDXREG(XGICR, 0x7a, 0x2c); */
97 /* outXGIIDXREG(XGICR, 0x82, 0xcc); */
98 /* outXGIIDXREG(XGICR, 0x8c, 0x0); */
100 outXGIIDXREG(XGICR, 0x99, 0x1);
101 outXGIIDXREG(XGICR, 0x41, 0x40);
104 for (i = 0; i < 0x4f; i++) {
105 inXGIIDXREG(XGISR, i, reg);
106 printk("\no 3c4 %x", i);
107 printk("\ni 3c5 => %x", reg);
110 for (i = 0; i < 0xF0; i++) {
111 inXGIIDXREG(XGICR, i, reg);
112 printk("\no 3d4 %x", i);
113 printk("\ni 3d5 => %x", reg);
116 outXGIIDXREG(XGIPART1,0x2F,1);
117 for (i=1; i < 0x50; i++) {
118 inXGIIDXREG(XGIPART1, i, reg);
119 printk("\no d004 %x", i);
120 printk("\ni d005 => %x", reg);
123 for (i=0; i < 0x50; i++) {
124 inXGIIDXREG(XGIPART2, i, reg);
125 printk("\no d010 %x", i);
126 printk("\ni d011 => %x", reg);
128 for (i=0; i < 0x50; i++) {
129 inXGIIDXREG(XGIPART3, i, reg);
130 printk("\no d012 %x",i);
131 printk("\ni d013 => %x",reg);
133 for (i=0; i < 0x50; i++) {
134 inXGIIDXREG(XGIPART4, i, reg);
135 printk("\no d014 %x",i);
136 printk("\ni d015 => %x",reg);
141 static inline void dumpVGAReg(void)
146 /* data for XGI components */
147 struct video_info xgi_video_info;
152 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
155 /* --------------- Hardware Access Routines -------------------------- */
157 static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
158 struct xgi_hw_device_info *HwDeviceExtension,
159 unsigned char modeno, unsigned char rateindex)
161 unsigned short ModeNo = modeno;
162 unsigned short ModeIdIndex = 0, ClockIndex = 0;
163 unsigned short RefreshRateTableIndex = 0;
165 /* unsigned long temp = 0; */
167 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
168 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
170 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
171 ModeIdIndex, XGI_Pr);
174 temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
176 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
180 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
181 RefreshRateTableIndex += (rateindex - 1);
184 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
185 if (HwDeviceExtension->jChipType < XGI_315H)
188 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
193 static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
194 struct xgi_hw_device_info *HwDeviceExtension,
195 unsigned char modeno, unsigned char rateindex,
196 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
197 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
200 unsigned short ModeNo = modeno;
201 unsigned short ModeIdIndex = 0, index = 0;
202 unsigned short RefreshRateTableIndex = 0;
204 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
205 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
206 unsigned char sr_data, cr_data, cr_data2;
207 unsigned long cr_data3;
208 int A, B, C, D, E, F, temp, j;
209 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
210 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
211 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
212 ModeIdIndex, XGI_Pr);
214 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
218 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
219 RefreshRateTableIndex += (rateindex - 1);
221 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
223 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
225 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
227 /* Horizontal total */
228 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
232 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
234 Horizontal display enable end
235 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
237 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
240 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
242 /* Horizontal retrace (=sync) start */
243 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
246 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
248 /* Horizontal blank start */
249 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
251 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
253 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
255 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
257 /* Horizontal blank end */
258 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
259 | ((unsigned short) (sr_data & 0x03) << 6);
261 /* Horizontal retrace (=sync) end */
262 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
264 temp = HBE - ((E - 1) & 255);
265 B = (temp > 0) ? temp : (temp + 256);
267 temp = HRE - ((E + F + 3) & 63);
268 C = (temp > 0) ? temp : (temp + 64);
272 *left_margin = D * 8;
273 *right_margin = F * 8;
276 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
278 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
280 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
283 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
284 | ((unsigned short) (cr_data2 & 0x20) << 4)
285 | ((unsigned short) (sr_data & 0x01) << 10);
288 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
290 /* Vertical display enable end */
292 VDE = (cr_data & 0xff) |
293 ((unsigned short) (cr_data2 & 0x02) << 7) |
294 ((unsigned short) (cr_data2 & 0x40) << 3) |
295 ((unsigned short) (sr_data & 0x02) << 9);
297 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
300 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
302 /* Vertical retrace (=sync) start */
303 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
304 | ((unsigned short) (cr_data2 & 0x80) << 2)
305 | ((unsigned short) (sr_data & 0x08) << 7);
308 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
310 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
312 /* Vertical blank start */
313 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
314 | ((unsigned short) (cr_data3 & 0x20) << 4)
315 | ((unsigned short) (sr_data & 0x04) << 8);
317 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
319 /* Vertical blank end */
320 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
321 temp = VBE - ((E - 1) & 511);
322 B = (temp > 0) ? temp : (temp + 512);
324 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
326 /* Vertical retrace (=sync) end */
327 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
328 temp = VRE - ((E + F - 1) & 31);
329 C = (temp > 0) ? temp : (temp + 32);
337 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
338 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
340 *sync |= FB_SYNC_VERT_HIGH_ACT;
342 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
343 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
345 *sync |= FB_SYNC_HOR_HIGH_ACT;
347 *vmode = FB_VMODE_NONINTERLACED;
348 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
349 *vmode = FB_VMODE_INTERLACED;
352 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
353 if (XGI_Pr->EModeIDTable[j].Ext_ModeID
354 == XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
355 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag
357 *vmode = FB_VMODE_DOUBLE;
368 static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
370 XGI_Pr->RelIO = BaseAddr;
371 XGI_Pr->P3c4 = BaseAddr + 0x14;
372 XGI_Pr->P3d4 = BaseAddr + 0x24;
373 XGI_Pr->P3c0 = BaseAddr + 0x10;
374 XGI_Pr->P3ce = BaseAddr + 0x1e;
375 XGI_Pr->P3c2 = BaseAddr + 0x12;
376 XGI_Pr->P3ca = BaseAddr + 0x1a;
377 XGI_Pr->P3c6 = BaseAddr + 0x16;
378 XGI_Pr->P3c7 = BaseAddr + 0x17;
379 XGI_Pr->P3c8 = BaseAddr + 0x18;
380 XGI_Pr->P3c9 = BaseAddr + 0x19;
381 XGI_Pr->P3da = BaseAddr + 0x2A;
382 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
383 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
384 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
385 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
386 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2; /* 301 palette address port registers */
390 void XGIfb_set_reg4(u16 port, unsigned long data)
392 outl((u32)(data & 0xffffffff), port);
395 u32 XGIfb_get_reg3(u16 port)
403 /* ------------ Interface for init & mode switching code ------------- */
405 unsigned char XGIfb_query_VGA_config_space(
406 struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
407 unsigned long set, unsigned long *value)
409 static struct pci_dev *pdev = NULL;
410 static unsigned char init = 0, valid_pdev = 0;
413 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
415 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
419 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
428 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
429 xgi_video_info.chip_id);
434 pci_read_config_dword(pdev, offset, (u32 *) value);
436 pci_write_config_dword(pdev, offset, (u32)(*value));
442 unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
443 unsigned long offset, unsigned long set, unsigned long *value)
445 static struct pci_dev *pdev = NULL;
446 static unsigned char init = 0, valid_pdev = 0;
451 switch (xgi_video_info.chip) {
453 nbridge_id = PCI_DEVICE_ID_XG_540;
456 nbridge_id = PCI_DEVICE_ID_XG_630;
459 nbridge_id = PCI_DEVICE_ID_XG_730;
462 nbridge_id = PCI_DEVICE_ID_XG_550;
465 nbridge_id = PCI_DEVICE_ID_XG_650;
468 nbridge_id = PCI_DEVICE_ID_XG_740;
475 pdev = pci_get_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
483 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
489 pci_read_config_dword(pdev, offset, (u32 *)value);
491 pci_write_config_dword(pdev, offset, (u32)(*value));
496 /* ------------------ Internal helper routines ----------------- */
498 static void XGIfb_search_mode(const char *name)
503 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
504 xgifb_mode_idx = DEFAULT_MODE;
505 if ((xgi_video_info.chip == XG21)
506 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
508 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
513 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
514 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
515 xgifb_mode_idx = DEFAULT_MODE;
516 if ((xgi_video_info.chip == XG21)
517 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
519 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
524 while (XGIbios_mode[i].mode_no != 0) {
525 l = min(strlen(name), strlen(XGIbios_mode[i].name));
526 if (!strncmp(name, XGIbios_mode[i].name, l)) {
534 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
537 static void XGIfb_search_vesamode(unsigned int vesamode)
543 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
544 xgifb_mode_idx = DEFAULT_MODE;
545 if ((xgi_video_info.chip == XG21)
546 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
548 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
553 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
555 while (XGIbios_mode[i].mode_no != 0) {
556 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode)
557 || (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
565 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
568 static int XGIfb_GetXG21LVDSData(void)
571 unsigned char *pData;
574 inXGIIDXREG(XGISR, 0x1e, tmp);
575 outXGIIDXREG(XGISR, 0x1e, tmp | 4);
577 pData = xgi_video_info.mmio_vbase + 0x20000;
578 if ((pData[0x0] == 0x55) && (pData[0x1] == 0xAA) && (pData[0x65] & 0x1)) {
579 i = pData[0x316] | (pData[0x317] << 8);
586 XGI21_LCDCapList[k].LVDS_Capability = pData[i]
587 | (pData[i + 1] << 8);
588 XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
590 XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
592 XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
594 XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
596 XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
598 XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
600 XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
601 | (pData[i + 15] << 8);
602 XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
603 | (pData[i + 17] << 8);
604 XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
605 XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
606 XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
607 XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
608 XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
609 XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
610 XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
614 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
615 / sizeof(struct XGI21_LVDSCapStruct))));
621 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
625 int XGIfb_mode_idx = 0;
628 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
629 && (XGIbios_mode[XGIfb_mode_idx].xres
630 <= XGI21_LCDCapList[0].LVDSHDE)) {
631 if ((XGIbios_mode[XGIfb_mode_idx].xres
632 == XGI21_LCDCapList[0].LVDSHDE)
633 && (XGIbios_mode[XGIfb_mode_idx].yres
634 == XGI21_LCDCapList[0].LVDSVDE)
635 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
636 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
645 return XGIfb_mode_idx;
648 static int XGIfb_validate_mode(int myindex)
652 if (xgi_video_info.chip == XG21) {
653 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
655 xres = XGI21_LCDCapList[0].LVDSHDE;
656 yres = XGI21_LCDCapList[0].LVDSVDE;
657 if (XGIbios_mode[myindex].xres > xres)
659 if (XGIbios_mode[myindex].yres > yres)
661 if ((XGIbios_mode[myindex].xres < xres)
662 && (XGIbios_mode[myindex].yres < yres)) {
663 if (XGIbios_mode[myindex].bpp > 8)
672 /* FIXME: for now, all is valid on XG27 */
673 if (xgi_video_info.chip == XG27)
676 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
679 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
681 switch (XGIhw_ext.ulCRT2LCDType) {
722 /* case LCD_320x480: */ /* TW: FSTN */
733 if (XGIbios_mode[myindex].xres > xres)
735 if (XGIbios_mode[myindex].yres > yres)
737 if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
738 (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
739 switch (XGIbios_mode[myindex].xres) {
741 if (XGIbios_mode[myindex].yres != 512)
743 if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
747 if ((XGIbios_mode[myindex].yres != 400)
748 && (XGIbios_mode[myindex].yres
753 if (XGIbios_mode[myindex].yres != 600)
757 if ((XGIbios_mode[myindex].yres != 600)
758 && (XGIbios_mode[myindex].yres
761 if ((XGIbios_mode[myindex].yres == 600)
762 && (XGIhw_ext.ulCRT2LCDType
767 if ((XGIbios_mode[myindex].yres) != 768)
769 if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
773 if ((XGIbios_mode[myindex].yres != 768)
774 && (XGIbios_mode[myindex].yres
777 if ((XGIbios_mode[myindex].yres == 768)
778 && (XGIhw_ext.ulCRT2LCDType
783 if (XGIbios_mode[myindex].yres != 1050)
787 if (XGIbios_mode[myindex].yres != 1200)
794 switch (XGIbios_mode[myindex].xres) {
796 if (XGIbios_mode[myindex].yres != 512)
800 if ((XGIbios_mode[myindex].yres != 400)
801 && (XGIbios_mode[myindex].yres
806 if (XGIbios_mode[myindex].yres != 600)
810 if (XGIbios_mode[myindex].yres != 768)
814 if ((XGIbios_mode[myindex].yres != 960)
815 && (XGIbios_mode[myindex].yres
818 if (XGIbios_mode[myindex].yres == 960) {
819 if (XGIhw_ext.ulCRT2LCDType
825 if (XGIbios_mode[myindex].yres != 1050)
829 if (XGIbios_mode[myindex].yres != 1200)
838 switch (XGIbios_mode[myindex].xres) {
844 if (xgi_video_info.TV_type == TVMODE_NTSC) {
845 if (XGIbios_mode[myindex].yres != 480)
847 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
848 if (XGIbios_mode[myindex].yres != 576)
851 /* TW: LVDS/CHRONTEL does not support 720 */
852 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
853 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
858 if (xgi_video_info.TV_type == TVMODE_NTSC) {
859 if (XGIbios_mode[myindex].bpp == 32)
862 /* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) */
863 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
864 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
865 if (xgi_video_info.chip < XGI_315H)
874 if (XGIbios_mode[myindex].xres > 1280)
882 static void XGIfb_search_crt2type(const char *name)
889 while (XGI_crt2type[i].type_no != -1) {
890 if (!strcmp(name, XGI_crt2type[i].name)) {
891 XGIfb_crt2type = XGI_crt2type[i].type_no;
892 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
897 if (XGIfb_crt2type < 0)
898 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
901 static void XGIfb_search_queuemode(const char *name)
908 while (XGI_queuemode[i].type_no != -1) {
909 if (!strcmp(name, XGI_queuemode[i].name)) {
910 XGIfb_queuemode = XGI_queuemode[i].type_no;
915 if (XGIfb_queuemode < 0)
916 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
919 static u8 XGIfb_search_refresh_rate(unsigned int rate)
924 xres = XGIbios_mode[xgifb_mode_idx].xres;
925 yres = XGIbios_mode[xgifb_mode_idx].yres;
928 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
929 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres
931 if (XGIfb_vrate[i].refresh == rate) {
932 XGIfb_rate_idx = XGIfb_vrate[i].idx;
934 } else if (XGIfb_vrate[i].refresh > rate) {
935 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
936 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
937 rate, XGIfb_vrate[i].refresh);
938 XGIfb_rate_idx = XGIfb_vrate[i].idx;
939 xgi_video_info.refresh_rate
940 = XGIfb_vrate[i].refresh;
941 } else if (((rate - XGIfb_vrate[i - 1].refresh)
942 <= 2) && (XGIfb_vrate[i].idx
944 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
945 rate, XGIfb_vrate[i-1].refresh);
946 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
947 xgi_video_info.refresh_rate
948 = XGIfb_vrate[i - 1].refresh;
951 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
952 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
953 rate, XGIfb_vrate[i].refresh);
954 XGIfb_rate_idx = XGIfb_vrate[i].idx;
960 if (XGIfb_rate_idx > 0) {
961 return XGIfb_rate_idx;
964 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
969 static void XGIfb_search_tvstd(const char *name)
976 while (XGI_tvtype[i].type_no != -1) {
977 if (!strcmp(name, XGI_tvtype[i].name)) {
978 XGIfb_tvmode = XGI_tvtype[i].type_no;
985 static unsigned char XGIfb_bridgeisslave(void)
987 unsigned char usScratchP1_00;
989 if (xgi_video_info.hasVB == HASVB_NONE)
992 inXGIIDXREG(XGIPART1, 0x00, usScratchP1_00);
993 if ((usScratchP1_00 & 0x50) == 0x10)
999 static unsigned char XGIfbcheckvretracecrt1(void)
1003 inXGIIDXREG(XGICR, 0x17, temp);
1007 inXGIIDXREG(XGISR, 0x1f, temp);
1011 if (inXGIREG(XGIINPSTAT) & 0x08)
1017 static unsigned char XGIfbcheckvretracecrt2(void)
1020 if (xgi_video_info.hasVB == HASVB_NONE)
1022 inXGIIDXREG(XGIPART1, 0x30, temp);
1029 static unsigned char XGIfb_CheckVBRetrace(void)
1031 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1032 if (XGIfb_bridgeisslave())
1033 return XGIfbcheckvretracecrt1();
1035 return XGIfbcheckvretracecrt2();
1037 return XGIfbcheckvretracecrt1();
1040 /* ----------- FBDev related routines for all series ----------- */
1042 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1044 switch (var->bits_per_pixel) {
1046 var->red.offset = var->green.offset = var->blue.offset = 0;
1047 var->red.length = var->green.length = var->blue.length = 6;
1048 xgi_video_info.video_cmap_len = 256;
1051 var->red.offset = 11;
1052 var->red.length = 5;
1053 var->green.offset = 5;
1054 var->green.length = 6;
1055 var->blue.offset = 0;
1056 var->blue.length = 5;
1057 var->transp.offset = 0;
1058 var->transp.length = 0;
1059 xgi_video_info.video_cmap_len = 16;
1062 var->red.offset = 16;
1063 var->red.length = 8;
1064 var->green.offset = 8;
1065 var->green.length = 8;
1066 var->blue.offset = 0;
1067 var->blue.length = 8;
1068 var->transp.offset = 24;
1069 var->transp.length = 8;
1070 xgi_video_info.video_cmap_len = 16;
1075 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1076 struct fb_info *info)
1079 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1081 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1083 #if defined(__powerpc__)
1084 u8 sr_data, cr_data;
1086 unsigned int drate = 0, hrate = 0;
1089 /* unsigned char reg, reg1; */
1091 DEBUGPRN("Inside do_set_var");
1092 /* 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); */
1094 info->var.xres_virtual = var->xres_virtual;
1095 info->var.yres_virtual = var->yres_virtual;
1096 info->var.bits_per_pixel = var->bits_per_pixel;
1098 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1100 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1102 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1104 /* var->yres <<= 1; */
1107 if (!htotal || !vtotal) {
1108 DPRINTK("XGIfb: Invalid 'var' information\n");
1110 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1111 var->pixclock, htotal, vtotal);
1113 if (var->pixclock && htotal && vtotal) {
1114 drate = 1000000000 / var->pixclock;
1115 hrate = (drate * 1000) / htotal;
1116 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1119 xgi_video_info.refresh_rate = 60;
1122 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1123 var->xres, var->yres, var->bits_per_pixel, xgi_video_info.refresh_rate);
1125 old_mode = xgifb_mode_idx;
1128 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1129 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1130 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1131 && (XGIbios_mode[xgifb_mode_idx].yres
1133 && (XGIbios_mode[xgifb_mode_idx].bpp
1134 == var->bits_per_pixel)) {
1135 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1143 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1145 xgifb_mode_idx = -1;
1147 if (xgifb_mode_idx < 0) {
1148 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1149 var->yres, var->bits_per_pixel);
1150 xgifb_mode_idx = old_mode;
1154 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1155 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1156 xgi_video_info.refresh_rate = 60;
1161 XGIfb_pre_setmode();
1162 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1163 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1166 info->fix.line_length = ((info->var.xres_virtual
1167 * info->var.bits_per_pixel) >> 6);
1169 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1171 outXGIIDXREG(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1172 outXGIIDXREG(XGISR, 0x0E, (info->fix.line_length & 0xff00) >> 8);
1174 XGIfb_post_setmode();
1176 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1177 XGIbios_mode[xgifb_mode_idx].xres,
1178 XGIbios_mode[xgifb_mode_idx].yres,
1179 XGIbios_mode[xgifb_mode_idx].bpp,
1180 xgi_video_info.refresh_rate);
1182 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1183 xgi_video_info.video_vwidth = info->var.xres_virtual;
1184 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1185 xgi_video_info.video_vheight = info->var.yres_virtual;
1186 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1187 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1188 xgi_video_info.video_linelength = info->var.xres_virtual
1189 * (xgi_video_info.video_bpp >> 3);
1190 switch (xgi_video_info.video_bpp) {
1192 xgi_video_info.DstColor = 0x0000;
1193 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1194 xgi_video_info.video_cmap_len = 256;
1195 #if defined(__powerpc__)
1196 inXGIIDXREG(XGICR, 0x4D, cr_data);
1197 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1201 xgi_video_info.DstColor = 0x8000;
1202 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1203 #if defined(__powerpc__)
1204 inXGIIDXREG(XGICR, 0x4D, cr_data);
1205 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1207 xgi_video_info.video_cmap_len = 16;
1210 xgi_video_info.DstColor = 0xC000;
1211 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1212 xgi_video_info.video_cmap_len = 16;
1213 #if defined(__powerpc__)
1214 inXGIIDXREG(XGICR, 0x4D, cr_data);
1215 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1219 xgi_video_info.video_cmap_len = 16;
1220 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1224 XGIfb_bpp_to_var(var); /*update ARGB info*/
1225 DEBUGPRN("End of do_set_var");
1232 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1236 /* printk("Inside pan_var"); */
1238 if (var->xoffset > (var->xres_virtual - var->xres)) {
1239 /* printk("Pan: xo: %d xv %d xr %d\n",
1240 var->xoffset, var->xres_virtual, var->xres); */
1243 if (var->yoffset > (var->yres_virtual - var->yres)) {
1244 /* printk("Pan: yo: %d yv %d yr %d\n",
1245 var->yoffset, var->yres_virtual, var->yres); */
1248 base = var->yoffset * var->xres_virtual + var->xoffset;
1250 /* calculate base bpp dep. */
1251 switch (var->bits_per_pixel) {
1263 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1265 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1266 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1267 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1268 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1269 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1271 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1272 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1273 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1274 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1275 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1276 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1278 /* printk("End of pan_var"); */
1283 void XGI_dispinfo(struct ap_data *rec)
1285 rec->minfo.bpp = xgi_video_info.video_bpp;
1286 rec->minfo.xres = xgi_video_info.video_width;
1287 rec->minfo.yres = xgi_video_info.video_height;
1288 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1289 rec->minfo.v_yres = xgi_video_info.video_vheight;
1290 rec->minfo.org_x = xgi_video_info.org_x;
1291 rec->minfo.org_y = xgi_video_info.org_y;
1292 rec->minfo.vrate = xgi_video_info.refresh_rate;
1293 rec->iobase = xgi_video_info.vga_base - 0x30;
1294 rec->mem_size = xgi_video_info.video_size;
1295 rec->disp_state = xgi_video_info.disp_state;
1296 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1297 rec->hasVB = xgi_video_info.hasVB;
1298 rec->TV_type = xgi_video_info.TV_type;
1299 rec->TV_plug = xgi_video_info.TV_plug;
1300 rec->chip = xgi_video_info.chip;
1303 static int XGIfb_open(struct fb_info *info, int user)
1308 static int XGIfb_release(struct fb_info *info, int user)
1313 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1317 switch (var->bits_per_pixel) {
1331 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1332 unsigned blue, unsigned transp, struct fb_info *info)
1334 if (regno >= XGIfb_get_cmap_len(&info->var))
1337 switch (info->var.bits_per_pixel) {
1339 outXGIREG(XGIDACA, regno);
1340 outXGIREG(XGIDACD, (red >> 10));
1341 outXGIREG(XGIDACD, (green >> 10));
1342 outXGIREG(XGIDACD, (blue >> 10));
1343 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1344 outXGIREG(XGIDAC2A, regno);
1345 outXGIREG(XGIDAC2D, (red >> 8));
1346 outXGIREG(XGIDAC2D, (green >> 8));
1347 outXGIREG(XGIDAC2D, (blue >> 8));
1351 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1352 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1359 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1366 static int XGIfb_set_par(struct fb_info *info)
1370 /* printk("XGIfb: inside set_par\n"); */
1371 err = XGIfb_do_set_var(&info->var, 1, info);
1374 XGIfb_get_fix(&info->fix, -1, info);
1375 /* printk("XGIfb: end of set_par\n"); */
1379 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1381 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1383 unsigned int vtotal = 0;
1384 unsigned int drate = 0, hrate = 0;
1386 int refresh_rate, search_idx;
1388 DEBUGPRN("Inside check_var");
1390 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1391 vtotal = var->upper_margin + var->yres + var->lower_margin
1394 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1395 vtotal = var->upper_margin + var->yres + var->lower_margin
1398 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1399 vtotal = var->upper_margin + (var->yres / 2)
1400 + var->lower_margin + var->vsync_len;
1402 vtotal = var->upper_margin + var->yres + var->lower_margin
1405 if (!(htotal) || !(vtotal))
1406 XGIFAIL("XGIfb: no valid timing data");
1408 if (var->pixclock && htotal && vtotal) {
1409 drate = 1000000000 / var->pixclock;
1410 hrate = (drate * 1000) / htotal;
1411 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1413 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1414 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1415 __func__, var->pixclock, htotal, vtotal,
1416 __func__, drate, hrate, xgi_video_info.refresh_rate);
1418 xgi_video_info.refresh_rate = 60;
1422 if ((var->pixclock) && (htotal)) {
1423 drate = 1E12 / var->pixclock;
1424 hrate = drate / htotal;
1425 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1430 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1431 if ((var->xres == 1024) && (var->yres == 600))
1435 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1436 (XGIbios_mode[search_idx].xres <= var->xres)) {
1437 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1438 (XGIbios_mode[search_idx].yres == var->yres) &&
1439 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1440 if (XGIfb_validate_mode(search_idx) > 0) {
1450 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1451 var->xres, var->yres, var->bits_per_pixel);
1453 while (XGIbios_mode[search_idx].mode_no != 0) {
1455 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1456 (var->yres <= XGIbios_mode[search_idx].yres) &&
1457 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1458 if (XGIfb_validate_mode(search_idx) > 0) {
1466 var->xres = XGIbios_mode[search_idx].xres;
1467 var->yres = XGIbios_mode[search_idx].yres;
1468 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1469 var->xres, var->yres, var->bits_per_pixel);
1472 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1473 var->xres, var->yres, var->bits_per_pixel);
1478 /* TW: TODO: Check the refresh rate */
1480 /* Adapt RGB settings */
1481 XGIfb_bpp_to_var(var);
1483 /* Sanity check for offsets */
1484 if (var->xoffset < 0)
1486 if (var->yoffset < 0)
1490 if (var->xres != var->xres_virtual)
1491 var->xres_virtual = var->xres;
1492 if (var->yres != var->yres_virtual)
1493 var->yres_virtual = var->yres;
1495 /* TW: Now patch yres_virtual if we use panning */
1496 /* May I do this? */
1497 /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1498 /* if (var->yres_virtual <= var->yres) { */
1499 /* TW: Paranoia check */
1500 /* var->yres_virtual = var->yres; */
1504 /* Truncate offsets to maximum if too high */
1505 if (var->xoffset > var->xres_virtual - var->xres)
1506 var->xoffset = var->xres_virtual - var->xres - 1;
1508 if (var->yoffset > var->yres_virtual - var->yres)
1509 var->yoffset = var->yres_virtual - var->yres - 1;
1511 /* Set everything else to 0 */
1512 var->red.msb_right =
1513 var->green.msb_right =
1514 var->blue.msb_right =
1515 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1517 DEBUGPRN("end of check_var");
1522 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1523 struct fb_info *info)
1527 /* printk("\nInside pan_display:\n"); */
1529 if (var->xoffset > (var->xres_virtual - var->xres))
1531 if (var->yoffset > (var->yres_virtual - var->yres))
1534 if (var->vmode & FB_VMODE_YWRAP) {
1535 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1539 if (var->xoffset + info->var.xres > info->var.xres_virtual
1540 || var->yoffset + info->var.yres
1541 > info->var.yres_virtual)
1544 err = XGIfb_pan_var(var);
1548 info->var.xoffset = var->xoffset;
1549 info->var.yoffset = var->yoffset;
1550 if (var->vmode & FB_VMODE_YWRAP)
1551 info->var.vmode |= FB_VMODE_YWRAP;
1553 info->var.vmode &= ~FB_VMODE_YWRAP;
1555 /* printk("End of pan_display\n"); */
1560 static int XGIfb_blank(int blank, struct fb_info *info)
1564 inXGIIDXREG(XGICR, 0x17, reg);
1571 outXGIIDXREG(XGICR, 0x17, reg);
1572 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1573 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1577 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1580 DEBUGPRN("inside ioctl");
1583 if (!capable(CAP_SYS_RAWIO))
1585 XGI_malloc((struct XGI_memreq *) arg);
1588 if (!capable(CAP_SYS_RAWIO))
1590 XGI_free(*(unsigned long *) arg);
1592 case FBIOGET_HWCINFO: {
1593 unsigned long *hwc_offset = (unsigned long *) arg;
1595 if (XGIfb_caps & HW_CURSOR_CAP)
1597 = XGIfb_hwcursor_vbase
1598 - (unsigned long) xgi_video_info.video_vbase;
1604 case FBIOPUT_MODEINFO: {
1605 struct mode_info *x = (struct mode_info *) arg;
1607 xgi_video_info.video_bpp = x->bpp;
1608 xgi_video_info.video_width = x->xres;
1609 xgi_video_info.video_height = x->yres;
1610 xgi_video_info.video_vwidth = x->v_xres;
1611 xgi_video_info.video_vheight = x->v_yres;
1612 xgi_video_info.org_x = x->org_x;
1613 xgi_video_info.org_y = x->org_y;
1614 xgi_video_info.refresh_rate = x->vrate;
1615 xgi_video_info.video_linelength = xgi_video_info.video_vwidth
1616 * (xgi_video_info.video_bpp >> 3);
1617 switch (xgi_video_info.video_bpp) {
1619 xgi_video_info.DstColor = 0x0000;
1620 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1621 xgi_video_info.video_cmap_len = 256;
1624 xgi_video_info.DstColor = 0x8000;
1625 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1626 xgi_video_info.video_cmap_len = 16;
1629 xgi_video_info.DstColor = 0xC000;
1630 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1631 xgi_video_info.video_cmap_len = 16;
1634 xgi_video_info.video_cmap_len = 16;
1635 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1641 case FBIOGET_DISPINFO:
1642 XGI_dispinfo((struct ap_data *) arg);
1644 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1646 struct XGIfb_info *x = (struct XGIfb_info *) arg;
1648 /* x->XGIfb_id = XGIFB_ID; */
1649 x->XGIfb_version = VER_MAJOR;
1650 x->XGIfb_revision = VER_MINOR;
1651 x->XGIfb_patchlevel = VER_LEVEL;
1652 x->chip_id = xgi_video_info.chip_id;
1653 x->memory = xgi_video_info.video_size / 1024;
1654 x->heapstart = xgi_video_info.heapstart / 1024;
1655 x->fbvidmode = XGIfb_mode_no;
1656 x->XGIfb_caps = XGIfb_caps;
1657 x->XGIfb_tqlen = 512; /* yet unused */
1658 x->XGIfb_pcibus = xgi_video_info.pcibus;
1659 x->XGIfb_pcislot = xgi_video_info.pcislot;
1660 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1661 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1662 x->XGIfb_lcda = XGIfb_detectedlcda;
1665 case XGIFB_GET_VBRSTATUS: {
1666 unsigned long *vbrstatus = (unsigned long *) arg;
1667 if (XGIfb_CheckVBRetrace())
1674 } DEBUGPRN("end of ioctl");
1679 /* ----------- FBDev related routines for all series ---------- */
1681 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1682 struct fb_info *info)
1684 DEBUGPRN("inside get_fix");
1685 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1687 strcpy(fix->id, myid);
1689 fix->smem_start = xgi_video_info.video_base;
1691 fix->smem_len = xgi_video_info.video_size;
1693 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1694 if (xgi_video_info.video_size > 0x1000000) {
1695 fix->smem_len = 0xD00000;
1696 } else if (xgi_video_info.video_size > 0x800000)
1697 fix->smem_len = 0x800000;
1699 fix->smem_len = 0x400000;
1701 fix->smem_len = XGIfb_mem * 1024;
1703 fix->type = video_type;
1705 if (xgi_video_info.video_bpp == 8)
1706 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1708 fix->visual = FB_VISUAL_DIRECTCOLOR;
1715 fix->line_length = xgi_video_info.video_linelength;
1716 fix->mmio_start = xgi_video_info.mmio_base;
1717 fix->mmio_len = xgi_video_info.mmio_size;
1718 if (xgi_video_info.chip >= XG40)
1719 fix->accel = FB_ACCEL_XGI_XABRE;
1721 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1723 DEBUGPRN("end of get_fix");
1727 static struct fb_ops XGIfb_ops = {
1728 .owner = THIS_MODULE,
1729 .fb_open = XGIfb_open,
1730 .fb_release = XGIfb_release,
1731 .fb_check_var = XGIfb_check_var,
1732 .fb_set_par = XGIfb_set_par,
1733 .fb_setcolreg = XGIfb_setcolreg,
1735 .fb_pan_display = XGIfb_pan_display,
1737 .fb_blank = XGIfb_blank,
1738 .fb_fillrect = cfb_fillrect,
1739 .fb_copyarea = cfb_copyarea,
1740 .fb_imageblit = cfb_imageblit,
1741 .fb_ioctl = XGIfb_ioctl,
1742 /* .fb_mmap = XGIfb_mmap, */
1745 /* ---------------- Chip generation dependent routines ---------------- */
1747 /* for XGI 315/550/650/740/330 */
1749 static int XGIfb_get_dram_size(void)
1755 /* xorg driver sets 32MB * 1 channel */
1756 if (xgi_video_info.chip == XG27)
1757 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1759 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1760 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1761 case XGI_DRAM_SIZE_1MB:
1762 xgi_video_info.video_size = 0x100000;
1764 case XGI_DRAM_SIZE_2MB:
1765 xgi_video_info.video_size = 0x200000;
1767 case XGI_DRAM_SIZE_4MB:
1768 xgi_video_info.video_size = 0x400000;
1770 case XGI_DRAM_SIZE_8MB:
1771 xgi_video_info.video_size = 0x800000;
1773 case XGI_DRAM_SIZE_16MB:
1774 xgi_video_info.video_size = 0x1000000;
1776 case XGI_DRAM_SIZE_32MB:
1777 xgi_video_info.video_size = 0x2000000;
1779 case XGI_DRAM_SIZE_64MB:
1780 xgi_video_info.video_size = 0x4000000;
1782 case XGI_DRAM_SIZE_128MB:
1783 xgi_video_info.video_size = 0x8000000;
1785 case XGI_DRAM_SIZE_256MB:
1786 xgi_video_info.video_size = 0x10000000;
1792 tmp = (reg & 0x0c) >> 2;
1793 switch (xgi_video_info.chip) {
1829 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1830 /* PLiad fixed for benchmarking and fb set */
1831 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1832 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1834 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1835 xgi_video_info.video_size, ChannelNum);
1840 static void XGIfb_detect_VB(void)
1844 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1846 switch (xgi_video_info.hasVB) {
1847 case HASVB_LVDS_CHRONTEL:
1848 case HASVB_CHRONTEL:
1852 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1856 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1858 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1867 if (XGIfb_crt2type != -1)
1868 /* TW: Override with option */
1869 xgi_video_info.disp_state = XGIfb_crt2type;
1870 else if (cr32 & XGI_VB_TV)
1871 xgi_video_info.disp_state = DISPTYPE_TV;
1872 else if (cr32 & XGI_VB_LCD)
1873 xgi_video_info.disp_state = DISPTYPE_LCD;
1874 else if (cr32 & XGI_VB_CRT2)
1875 xgi_video_info.disp_state = DISPTYPE_CRT2;
1877 xgi_video_info.disp_state = 0;
1879 if (XGIfb_tvplug != -1)
1880 /* PR/TW: Override with option */
1881 xgi_video_info.TV_plug = XGIfb_tvplug;
1882 else if (cr32 & XGI_VB_HIVISION) {
1883 xgi_video_info.TV_type = TVMODE_HIVISION;
1884 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1885 } else if (cr32 & XGI_VB_SVIDEO)
1886 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1887 else if (cr32 & XGI_VB_COMPOSITE)
1888 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1889 else if (cr32 & XGI_VB_SCART)
1890 xgi_video_info.TV_plug = TVPLUG_SCART;
1892 if (xgi_video_info.TV_type == 0) {
1893 /* TW: PAL/NTSC changed for 650 */
1894 if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
1897 inXGIIDXREG(XGICR, 0x38, temp);
1899 xgi_video_info.TV_type = TVMODE_PAL;
1901 xgi_video_info.TV_type = TVMODE_NTSC;
1905 inXGIIDXREG(XGICR, 0x79, temp);
1907 xgi_video_info.TV_type = TVMODE_PAL;
1909 xgi_video_info.TV_type = TVMODE_NTSC;
1913 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1914 if (XGIfb_forcecrt1 != -1) {
1915 if (XGIfb_forcecrt1)
1922 static void XGIfb_get_VB_type(void)
1926 if (!XGIfb_has_VB()) {
1927 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1928 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1929 case XGI310_EXTERNAL_CHIP_LVDS:
1930 xgi_video_info.hasVB = HASVB_LVDS;
1932 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1933 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1941 static int XGIfb_has_VB(void)
1945 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1946 switch (vb_chipid) {
1948 xgi_video_info.hasVB = HASVB_301;
1951 xgi_video_info.hasVB = HASVB_302;
1954 xgi_video_info.hasVB = HASVB_NONE;
1960 /* ------------------ Sensing routines ------------------ */
1962 /* TW: Determine and detect attached devices on XGI30x */
1963 int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1967 outXGIIDXREG(XGIPART4, 0x11, tempbl);
1968 temp = tempbh | tempcl;
1969 setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1970 for (i = 0; i < 10; i++)
1971 XGI_LongWait(&XGI_Pr);
1973 inXGIIDXREG(XGIPART4, 0x03, temp);
1979 void XGI_Sense30x(void)
1982 u8 testsvhs_tempbl, testsvhs_tempbh;
1983 u8 testsvhs_tempcl, testsvhs_tempch;
1984 u8 testcvbs_tempbl, testcvbs_tempbh;
1985 u8 testcvbs_tempcl, testcvbs_tempch;
1986 u8 testvga2_tempbl, testvga2_tempbh;
1987 u8 testvga2_tempcl, testvga2_tempch;
1990 inXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
1991 outXGIIDXREG(XGIPART4, 0x0d, (backupP4_0d | 0x04));
1993 testvga2_tempbh = 0x00;
1994 testvga2_tempbl = 0xd1;
1995 testsvhs_tempbh = 0x00;
1996 testsvhs_tempbl = 0xb9;
1997 testcvbs_tempbh = 0x00;
1998 testcvbs_tempbl = 0xb3;
1999 if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
2001 testvga2_tempbh = 0x01;
2002 testvga2_tempbl = 0x90;
2003 testsvhs_tempbh = 0x01;
2004 testsvhs_tempbl = 0x6b;
2005 testcvbs_tempbh = 0x01;
2006 testcvbs_tempbl = 0x74;
2007 if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
2008 || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2009 testvga2_tempbh = 0x00;
2010 testvga2_tempbl = 0x00;
2011 testsvhs_tempbh = 0x02;
2012 testsvhs_tempbl = 0x00;
2013 testcvbs_tempbh = 0x01;
2014 testcvbs_tempbl = 0x00;
2017 if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
2019 inXGIIDXREG(XGIPART4, 0x01, myflag);
2020 if (myflag & 0x04) {
2021 testvga2_tempbh = 0x00;
2022 testvga2_tempbl = 0xfd;
2023 testsvhs_tempbh = 0x00;
2024 testsvhs_tempbl = 0xdd;
2025 testcvbs_tempbh = 0x00;
2026 testcvbs_tempbl = 0xee;
2029 if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
2030 == VB_CHIP_302LV)) {
2031 testvga2_tempbh = 0x00;
2032 testvga2_tempbl = 0x00;
2033 testvga2_tempch = 0x00;
2034 testvga2_tempcl = 0x00;
2035 testsvhs_tempch = 0x04;
2036 testsvhs_tempcl = 0x08;
2037 testcvbs_tempch = 0x08;
2038 testcvbs_tempcl = 0x08;
2040 testvga2_tempch = 0x0e;
2041 testvga2_tempcl = 0x08;
2042 testsvhs_tempch = 0x06;
2043 testsvhs_tempcl = 0x04;
2044 testcvbs_tempch = 0x08;
2045 testcvbs_tempcl = 0x04;
2048 if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
2049 || testvga2_tempbl) {
2050 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2051 testvga2_tempcl, testvga2_tempch);
2053 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2054 orXGIIDXREG(XGICR, 0x32, 0x10);
2058 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
2061 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2062 /* TW: So we can be sure that there IS a SVHS output */
2063 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2064 orXGIIDXREG(XGICR, 0x32, 0x02);
2068 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2069 testcvbs_tempcl, testcvbs_tempch);
2071 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2072 /* TW: So we can be sure that there IS a CVBS output */
2073 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2074 orXGIIDXREG(XGICR, 0x32, 0x01);
2077 XGIDoSense(0, 0, 0, 0);
2079 outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
2082 /* ------------------------ Heap routines -------------------------- */
2084 static int XGIfb_heap_init(void)
2089 int agp_enabled = 1;
2091 unsigned long *cmdq_baseport = NULL;
2092 unsigned long *read_port = NULL;
2093 unsigned long *write_port = NULL;
2094 XGI_CMDTYPE cmd_type;
2096 struct agp_kern_info *agp_info;
2097 struct agp_memory *agp;
2101 /* TW: The heap start is either set manually using the "mem" parameter, or
2102 * defaults as follows:
2103 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2104 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2105 * -) If 4MB or less is available, let it start at 4MB.
2106 * This is for avoiding a clash with X driver which uses the beginning
2107 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2109 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2110 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2112 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
2113 if (xgi_video_info.video_size > 0x1000000)
2114 xgi_video_info.heapstart = 0xD00000;
2115 else if (xgi_video_info.video_size > 0x800000)
2116 xgi_video_info.heapstart = 0x800000;
2118 xgi_video_info.heapstart = 0x400000;
2120 xgi_video_info.heapstart = XGIfb_mem * 1024;
2122 XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
2123 + xgi_video_info.heapstart);
2124 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2125 (int)(xgi_video_info.heapstart / 1024));
2127 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
2128 + xgi_video_info.video_size;
2129 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2131 /* TW: Now initialize the 310 series' command queue mode.
2132 * On 310/325, there are three queue modes available which
2133 * are chosen by setting bits 7:5 in SR26:
2134 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2135 * track of the queue, the FIFO, command parsing and so
2136 * on. This is the one comparable to the 300 series.
2137 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2138 * have to do queue management himself. Register 0x85c4 will
2139 * hold the location of the next free queue slot, 0x85c8
2140 * is the "queue read pointer" whose way of working is
2141 * unknown to me. Anyway, this mode would require a
2142 * translation of the MMIO commands to some kind of
2143 * accelerator assembly and writing these commands
2144 * to the memory location pointed to by 0x85c4.
2145 * We will not use this, as nobody knows how this
2146 * "assembly" works, and as it would require a complete
2147 * re-write of the accelerator code.
2148 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2149 * queue in AGP memory space.
2151 * SR26 bit 4 is called "Bypass H/W queue".
2152 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2153 * SR26 bit 0 resets the queue
2154 * Size of queue memory is encoded in bits 3:2 like this:
2159 * The queue location is to be written to 0x85C0.
2162 cmdq_baseport = (unsigned long *) (xgi_video_info.mmio_vbase
2163 + MMIO_QUEUE_PHYBASE);
2164 write_port = (unsigned long *) (xgi_video_info.mmio_vbase
2165 + MMIO_QUEUE_WRITEPORT);
2166 read_port = (unsigned long *) (xgi_video_info.mmio_vbase
2167 + MMIO_QUEUE_READPORT);
2169 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2171 agp_size = COMMAND_QUEUE_AREA_SIZE;
2174 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2175 agp_info = vzalloc(sizeof(*agp_info));
2176 agp_copy_info(agp_info);
2178 agp_backend_acquire();
2180 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
2183 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2186 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2187 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2188 /* TODO: Free AGP memory here */
2199 /* TW: Now select the queue mode */
2201 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2202 cmd_type = AGP_CMD_QUEUE;
2203 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2204 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2205 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2206 cmd_type = VM_CMD_QUEUE;
2207 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2209 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2210 cmd_type = MMIO_CMD;
2215 temp = XGI_CMD_QUEUE_SIZE_512k;
2218 temp = XGI_CMD_QUEUE_SIZE_1M;
2221 temp = XGI_CMD_QUEUE_SIZE_2M;
2224 temp = XGI_CMD_QUEUE_SIZE_4M;
2231 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2232 agp_info->aper_base, agp->physical, agp_size/1024);
2234 agp_phys = agp_info->aper_base + agp->physical;
2236 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2237 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2239 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2241 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2243 *write_port = *read_port;
2245 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2246 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2248 *cmdq_baseport = agp_phys;
2250 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2255 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2256 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2258 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2260 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2262 *write_port = *read_port;
2264 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2265 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2267 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2269 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2271 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2272 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2277 /* printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); */
2278 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2279 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2280 * enough. Reserve memory in any way.
2282 /* FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; */
2283 /* FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; */
2285 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); */
2286 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); */
2288 /* FIXME *write_port = *read_port; */
2290 /* FIXME *//* TW: Set Auto_Correction bit */
2291 /* FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); */
2292 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); */
2294 /* FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; */
2296 /* FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; */
2298 /* FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", */
2299 /* FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); */
2303 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2304 top of the videoRAM, right below the TB memory area (if used). */
2305 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2306 XGIfb_heap_end -= XGIfb_hwcursor_size;
2307 XGIfb_heap_size -= XGIfb_hwcursor_size;
2308 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2310 XGIfb_caps |= HW_CURSOR_CAP;
2312 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2313 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2316 XGIfb_heap.poha_chain = NULL;
2317 XGIfb_heap.poh_freelist = NULL;
2319 poh = XGIfb_poh_new_node();
2324 poh->poh_next = &XGIfb_heap.oh_free;
2325 poh->poh_prev = &XGIfb_heap.oh_free;
2326 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2327 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2329 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2330 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2331 (unsigned int) poh->size / 1024);
2333 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2334 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2336 XGIfb_heap.oh_free.poh_next = poh;
2337 XGIfb_heap.oh_free.poh_prev = poh;
2338 XGIfb_heap.oh_free.size = 0;
2339 XGIfb_heap.max_freesize = poh->size;
2341 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2342 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2343 XGIfb_heap.oh_used.size = SENTINEL;
2348 static XGI_OH *XGIfb_poh_new_node(void)
2355 if (XGIfb_heap.poh_freelist == NULL) {
2356 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2360 poha->poha_next = XGIfb_heap.poha_chain;
2361 XGIfb_heap.poha_chain = poha;
2363 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
2366 poh = &poha->aoh[0];
2367 for (i = cOhs - 1; i != 0; i--) {
2368 poh->poh_next = poh + 1;
2372 poh->poh_next = NULL;
2373 XGIfb_heap.poh_freelist = &poha->aoh[0];
2376 poh = XGIfb_heap.poh_freelist;
2377 XGIfb_heap.poh_freelist = poh->poh_next;
2382 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2388 if (size > XGIfb_heap.max_freesize) {
2389 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2390 (unsigned int) size / 1024);
2394 pohThis = XGIfb_heap.oh_free.poh_next;
2396 while (pohThis != &XGIfb_heap.oh_free) {
2397 if (size <= pohThis->size) {
2401 pohThis = pohThis->poh_next;
2405 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2406 (unsigned int) size / 1024);
2410 if (size == pohThis->size) {
2412 XGIfb_delete_node(pohThis);
2414 pohRoot = XGIfb_poh_new_node();
2416 if (pohRoot == NULL)
2419 pohRoot->offset = pohThis->offset;
2420 pohRoot->size = size;
2422 pohThis->offset += size;
2423 pohThis->size -= size;
2426 XGIfb_heap.max_freesize -= size;
2428 pohThis = &XGIfb_heap.oh_used;
2429 XGIfb_insert_node(pohThis, pohRoot);
2434 static void XGIfb_delete_node(XGI_OH *poh)
2439 poh_prev = poh->poh_prev;
2440 poh_next = poh->poh_next;
2442 poh_prev->poh_next = poh_next;
2443 poh_next->poh_prev = poh_prev;
2447 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2451 pohTemp = pohList->poh_next;
2453 pohList->poh_next = poh;
2454 pohTemp->poh_prev = poh;
2456 poh->poh_prev = pohList;
2457 poh->poh_next = pohTemp;
2460 static XGI_OH *XGIfb_poh_free(unsigned long base)
2466 unsigned long ulUpper;
2467 unsigned long ulLower;
2470 poh_freed = XGIfb_heap.oh_used.poh_next;
2472 while (poh_freed != &XGIfb_heap.oh_used) {
2473 if (poh_freed->offset == base) {
2478 poh_freed = poh_freed->poh_next;
2484 XGIfb_heap.max_freesize += poh_freed->size;
2486 poh_prev = poh_next = NULL;
2487 ulUpper = poh_freed->offset + poh_freed->size;
2488 ulLower = poh_freed->offset;
2490 pohThis = XGIfb_heap.oh_free.poh_next;
2492 while (pohThis != &XGIfb_heap.oh_free) {
2493 if (pohThis->offset == ulUpper)
2495 else if ((pohThis->offset + pohThis->size) == ulLower)
2498 pohThis = pohThis->poh_next;
2501 XGIfb_delete_node(poh_freed);
2503 if (poh_prev && poh_next) {
2504 poh_prev->size += (poh_freed->size + poh_next->size);
2505 XGIfb_delete_node(poh_next);
2506 XGIfb_free_node(poh_freed);
2507 XGIfb_free_node(poh_next);
2512 poh_prev->size += poh_freed->size;
2513 XGIfb_free_node(poh_freed);
2518 poh_next->size += poh_freed->size;
2519 poh_next->offset = poh_freed->offset;
2520 XGIfb_free_node(poh_freed);
2524 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2529 static void XGIfb_free_node(XGI_OH *poh)
2534 poh->poh_next = XGIfb_heap.poh_freelist;
2535 XGIfb_heap.poh_freelist = poh;
2539 void XGI_malloc(struct XGI_memreq *req)
2543 poh = XGIfb_poh_allocate(req->size);
2548 DPRINTK("XGIfb: Video RAM allocation failed\n");
2550 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2551 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2553 req->offset = poh->offset;
2554 req->size = poh->size;
2559 void XGI_free(unsigned long base)
2563 poh = XGIfb_poh_free(base);
2566 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2567 (unsigned int) base);
2571 /* --------------------- SetMode routines ------------------------- */
2573 static void XGIfb_pre_setmode(void)
2575 u8 cr30 = 0, cr31 = 0;
2577 inXGIIDXREG(XGICR, 0x31, cr31);
2580 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2582 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2583 cr31 |= XGI_DRIVER_MODE;
2586 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2587 cr31 |= XGI_DRIVER_MODE;
2590 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2591 cr30 = (XGI_VB_OUTPUT_HIVISION
2592 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2593 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2594 cr30 = (XGI_VB_OUTPUT_SVIDEO
2595 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2596 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2597 cr30 = (XGI_VB_OUTPUT_COMPOSITE
2598 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2599 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2600 cr30 = (XGI_VB_OUTPUT_SCART
2601 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2602 cr31 |= XGI_DRIVER_MODE;
2604 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2609 default: /* disable CRT2 */
2611 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2614 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2615 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2616 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2619 static void XGIfb_post_setmode(void)
2622 unsigned char doit = 1;
2624 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2625 outXGIIDXREG(XGICR, 0x13, 0x00);
2626 setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
2629 if (xgi_video_info.video_bpp == 8) {
2630 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2631 if ((xgi_video_info.hasVB == HASVB_LVDS)
2632 || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2635 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2636 if (xgi_video_info.disp_state & DISPTYPE_LCD)
2640 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2641 if (xgi_video_info.hasVB != HASVB_NONE) {
2642 inXGIIDXREG(XGIPART1, 0x00, reg);
2644 if ((reg & 0x50) == 0x10)
2651 inXGIIDXREG(XGICR, 0x17, reg);
2652 if ((XGIfb_crt1off) && (doit))
2656 outXGIIDXREG(XGICR, 0x17, reg);
2658 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2660 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
2663 inXGIIDXREG(XGIPART4, 0x01, reg);
2665 if (reg < 0xB0) { /* Set filter for XGI301 */
2667 switch (xgi_video_info.video_width) {
2669 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2672 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2675 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2678 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2685 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2687 if (xgi_video_info.TV_type == TVMODE_NTSC) {
2689 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2691 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2693 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2695 } else if (xgi_video_info.TV_plug
2696 == TVPLUG_COMPOSITE) {
2698 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2700 switch (xgi_video_info.video_width) {
2702 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2703 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2704 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2705 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2708 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2709 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2710 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2711 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2714 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2715 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2716 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2717 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2722 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2724 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2726 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2728 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2730 } else if (xgi_video_info.TV_plug
2731 == TVPLUG_COMPOSITE) {
2733 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2735 switch (xgi_video_info.video_width) {
2737 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2738 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2739 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2740 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2743 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2744 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2745 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2746 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2749 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2750 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2751 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2752 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2758 if ((filter >= 0) && (filter <= 7)) {
2759 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2760 XGI_TV_filter[filter_tb].filter[filter][0],
2761 XGI_TV_filter[filter_tb].filter[filter][1],
2762 XGI_TV_filter[filter_tb].filter[filter][2],
2763 XGI_TV_filter[filter_tb].filter[filter][3]
2768 (XGI_TV_filter[filter_tb].filter[filter][0]));
2772 (XGI_TV_filter[filter_tb].filter[filter][1]));
2776 (XGI_TV_filter[filter_tb].filter[filter][2]));
2780 (XGI_TV_filter[filter_tb].filter[filter][3]));
2789 XGIINITSTATIC int __init XGIfb_setup(char *options)
2793 xgi_video_info.refresh_rate = 0;
2795 printk(KERN_INFO "XGIfb: Options %s\n", options);
2797 if (!options || !*options)
2800 while ((this_opt = strsep(&options, ",")) != NULL) {
2805 if (!strncmp(this_opt, "mode:", 5)) {
2806 XGIfb_search_mode(this_opt + 5);
2807 } else if (!strncmp(this_opt, "vesa:", 5)) {
2808 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2809 } else if (!strncmp(this_opt, "mode:", 5)) {
2810 XGIfb_search_mode(this_opt + 5);
2811 } else if (!strncmp(this_opt, "vesa:", 5)) {
2812 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2813 } else if (!strncmp(this_opt, "vrate:", 6)) {
2814 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2815 } else if (!strncmp(this_opt, "rate:", 5)) {
2816 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2817 } else if (!strncmp(this_opt, "off", 3)) {
2819 } else if (!strncmp(this_opt, "crt1off", 7)) {
2821 } else if (!strncmp(this_opt, "filter:", 7)) {
2822 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2823 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2824 XGIfb_search_crt2type(this_opt + 14);
2825 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2826 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2827 } else if (!strncmp(this_opt, "tvmode:", 7)) {
2828 XGIfb_search_tvstd(this_opt + 7);
2829 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2830 XGIfb_search_tvstd(this_opt + 7);
2831 } else if (!strncmp(this_opt, "mem:", 4)) {
2832 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2833 } else if (!strncmp(this_opt, "dstn", 4)) {
2835 /* TW: DSTN overrules forcecrt2type */
2836 XGIfb_crt2type = DISPTYPE_LCD;
2837 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2838 XGIfb_search_queuemode(this_opt + 10);
2839 } else if (!strncmp(this_opt, "pdc:", 4)) {
2840 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2841 if (XGIfb_pdc & ~0x3c) {
2842 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2845 } else if (!strncmp(this_opt, "noypan", 6)) {
2847 } else if (!strncmp(this_opt, "userom:", 7)) {
2848 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2849 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2850 /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2852 XGIfb_search_mode(this_opt);
2853 /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2856 /* TW: Acceleration only with MMIO mode */
2857 if ((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2860 /* TW: Panning only with acceleration */
2864 printk("\nxgifb: outa xgifb_setup 3450");
2868 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
2870 void __iomem *rom_address;
2871 unsigned char *rom_copy;
2874 rom_address = pci_map_rom(dev, &rom_size);
2875 if (rom_address == NULL)
2878 rom_copy = vzalloc(XGIFB_ROM_SIZE);
2879 if (rom_copy == NULL)
2882 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
2883 memcpy_fromio(rom_copy, rom_address, rom_size);
2886 pci_unmap_rom(dev, rom_address);
2890 static int __devinit xgifb_probe(struct pci_dev *pdev,
2891 const struct pci_device_id *ent)
2901 XGIfb_registered = 0;
2903 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2904 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2908 xgi_video_info.chip_id = pdev->device;
2909 pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2910 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2911 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2912 XGIvga_enabled = reg16 & 0x01;
2914 xgi_video_info.pcibus = pdev->bus->number;
2915 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2916 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2917 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2918 xgi_video_info.subsysdevice = pdev->subsystem_device;
2920 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2921 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2922 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2923 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2924 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2925 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2926 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2927 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2929 if (pci_enable_device(pdev)) {
2934 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2936 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2937 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2939 if (reg1 != 0xa1) { /*I/O error */
2940 printk("\nXGIfb: I/O error!!!");
2945 switch (xgi_video_info.chip_id) {
2946 case PCI_DEVICE_ID_XG_20:
2947 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2948 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2949 if (CR48&GPIOG_READ)
2950 xgi_video_info.chip = XG21;
2952 xgi_video_info.chip = XG20;
2953 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2954 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2956 case PCI_DEVICE_ID_XG_40:
2957 xgi_video_info.chip = XG40;
2958 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2959 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2961 case PCI_DEVICE_ID_XG_41:
2962 xgi_video_info.chip = XG41;
2963 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2964 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2966 case PCI_DEVICE_ID_XG_42:
2967 xgi_video_info.chip = XG42;
2968 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2969 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2971 case PCI_DEVICE_ID_XG_27:
2972 xgi_video_info.chip = XG27;
2973 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2974 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2981 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
2982 XGIhw_ext.jChipType = xgi_video_info.chip;
2984 switch (xgi_video_info.chip) {
2992 XGIhw_ext.bIntegratedMMEnabled = 1;
2998 XGIhw_ext.pDevice = NULL;
2999 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
3000 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
3001 if (XGIhw_ext.pjVirtualRomBase)
3002 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
3004 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3006 XGIhw_ext.pjVirtualRomBase = NULL;
3007 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3009 XGIhw_ext.pjCustomizedROMImage = NULL;
3010 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3011 /* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
3012 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3014 if (!XGIvga_enabled) {
3015 /* Mapping Max FB Size for 315 Init */
3016 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3017 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3019 printk("XGIfb: XGIInit() ...");
3020 /* XGIInitNewt for LINUXBIOS only */
3021 if (XGIInitNew(&XGIhw_ext))
3027 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3033 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3034 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3036 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3038 /* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
3039 /* Set SR13 ,14 temporarily for UDtech */
3040 outXGIIDXREG(XGISR, 0x13, 0x45);
3041 outXGIIDXREG(XGISR, 0x14, 0x51);
3046 if (XGIfb_get_dram_size()) {
3047 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3052 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3053 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3054 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3055 /* Enable 2D accelerator engine */
3056 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3059 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3061 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
3062 printk("unable request memory size %x", xgi_video_info.video_size);
3063 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3064 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3069 if (!request_mem_region(xgi_video_info.mmio_base,
3070 xgi_video_info.mmio_size,
3072 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3077 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3078 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3079 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
3080 xgi_video_info.mmio_size);
3082 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3083 xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
3085 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3086 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
3087 xgi_video_info.mmio_size / 1024);
3088 printk("XGIfb: XGIInitNew() ...");
3089 if (XGIInitNew(&XGIhw_ext))
3094 if (XGIfb_heap_init())
3095 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3097 xgi_video_info.mtrr = (unsigned int) 0;
3099 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3100 xgi_video_info.hasVB = HASVB_NONE;
3101 if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
3102 xgi_video_info.hasVB = HASVB_NONE;
3103 } else if (xgi_video_info.chip == XG21) {
3104 inXGIIDXREG(XGICR, 0x38, CR38);
3105 if ((CR38&0xE0) == 0xC0) {
3106 xgi_video_info.disp_state = DISPTYPE_LCD;
3107 if (!XGIfb_GetXG21LVDSData()) {
3109 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3110 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3111 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3112 XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
3116 } else if ((CR38&0xE0) == 0x60) {
3117 xgi_video_info.hasVB = HASVB_CHRONTEL;
3119 xgi_video_info.hasVB = HASVB_NONE;
3122 XGIfb_get_VB_type();
3125 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3127 XGIhw_ext.ulExternalChip = 0;
3129 switch (xgi_video_info.hasVB) {
3131 inXGIIDXREG(XGIPART4, 0x01, reg);
3133 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3134 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3135 } else if (reg >= 0xD0) {
3136 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3137 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
3139 /* else if (reg >= 0xB0) {
3140 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3141 inXGIIDXREG(XGIPART4, 0x23, reg1);
3142 printk("XGIfb: XGI301B bridge detected\n");
3145 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3146 printk("XGIfb: XGI301 bridge detected\n");
3150 inXGIIDXREG(XGIPART4, 0x01, reg);
3152 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3153 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3154 } else if (reg >= 0xD0) {
3155 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3156 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3157 } else if (reg >= 0xB0) {
3158 inXGIIDXREG(XGIPART4, 0x23, reg1);
3160 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3163 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3164 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3168 XGIhw_ext.ulExternalChip = 0x1;
3169 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3171 case HASVB_TRUMPION:
3172 XGIhw_ext.ulExternalChip = 0x2;
3173 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3175 case HASVB_CHRONTEL:
3176 XGIhw_ext.ulExternalChip = 0x4;
3177 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3179 case HASVB_LVDS_CHRONTEL:
3180 XGIhw_ext.ulExternalChip = 0x5;
3181 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3184 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3188 if (xgi_video_info.hasVB != HASVB_NONE)
3191 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3193 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3195 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3197 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3200 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3202 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3204 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3208 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3212 XGIfb_detectedpdc = 0;
3214 XGIfb_detectedlcda = 0xff;
3217 /* TW: Try to find about LCDA */
3219 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3220 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3221 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
3223 inXGIIDXREG(XGICR, 0x34, tmp);
3225 /* Currently on LCDA? (Some BIOSes leave CR38) */
3226 inXGIIDXREG(XGICR, 0x38, tmp);
3227 if ((tmp & 0x03) == 0x03) {
3228 /* XGI_Pr.XGI_UseLCDA = 1; */
3230 /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
3231 inXGIIDXREG(XGICR, 0x35, tmp);
3233 /* XGI_Pr.XGI_UseLCDA = 1; */
3235 inXGIIDXREG(XGICR, 0x30, tmp);
3237 inXGIIDXREG(XGIPART1, 0x13, tmp);
3239 /* XGI_Pr.XGI_UseLCDA = 1; */
3250 if (xgifb_mode_idx >= 0)
3251 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3253 if (xgifb_mode_idx < 0) {
3254 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3256 xgifb_mode_idx = DEFAULT_LCDMODE;
3257 if (xgi_video_info.chip == XG21)
3258 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3261 xgifb_mode_idx = DEFAULT_TVMODE;
3264 xgifb_mode_idx = DEFAULT_MODE;
3269 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3271 if (xgi_video_info.refresh_rate == 0)
3272 xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
3273 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
3274 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3275 xgi_video_info.refresh_rate = 60;
3278 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3279 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3280 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3281 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3282 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3283 switch (xgi_video_info.video_bpp) {
3285 xgi_video_info.DstColor = 0x0000;
3286 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3287 xgi_video_info.video_cmap_len = 256;
3290 xgi_video_info.DstColor = 0x8000;
3291 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3292 xgi_video_info.video_cmap_len = 16;
3295 xgi_video_info.DstColor = 0xC000;
3296 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3297 xgi_video_info.video_cmap_len = 16;
3300 xgi_video_info.video_cmap_len = 16;
3301 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3305 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3306 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3307 xgi_video_info.refresh_rate);
3309 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3310 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3311 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3313 XGIfb_bpp_to_var(&default_var);
3315 default_var.pixclock = (u32) (1000000000 /
3316 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3317 XGIfb_mode_no, XGIfb_rate_idx));
3319 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3320 XGIfb_mode_no, XGIfb_rate_idx,
3321 &default_var.left_margin, &default_var.right_margin,
3322 &default_var.upper_margin, &default_var.lower_margin,
3323 &default_var.hsync_len, &default_var.vsync_len,
3324 &default_var.sync, &default_var.vmode)) {
3326 if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3327 default_var.yres <<= 1;
3328 default_var.yres_virtual <<= 1;
3329 } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3330 default_var.pixclock >>= 1;
3331 default_var.yres >>= 1;
3332 default_var.yres_virtual >>= 1;
3337 fb_info->flags = FBINFO_FLAG_DEFAULT;
3338 fb_info->var = default_var;
3339 fb_info->fix = XGIfb_fix;
3340 fb_info->par = &xgi_video_info;
3341 fb_info->screen_base = xgi_video_info.video_vbase;
3342 fb_info->fbops = &XGIfb_ops;
3343 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3344 fb_info->pseudo_palette = pseudo_palette;
3346 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3349 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3350 (unsigned int) xgi_video_info.video_size,
3351 MTRR_TYPE_WRCOMB, 1);
3352 if (xgi_video_info.mtrr)
3353 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3356 if (register_framebuffer(fb_info) < 0) {
3361 XGIfb_registered = 1;
3363 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3364 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3373 iounmap(xgi_video_info.mmio_vbase);
3374 iounmap(xgi_video_info.video_vbase);
3375 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
3377 release_mem_region(xgi_video_info.video_base,
3378 xgi_video_info.video_size);
3380 vfree(XGIhw_ext.pjVirtualRomBase);
3381 framebuffer_release(fb_info);
3385 /*****************************************************/
3386 /* PCI DEVICE HANDLING */
3387 /*****************************************************/
3389 static void __devexit xgifb_remove(struct pci_dev *pdev)
3391 unregister_framebuffer(fb_info);
3392 iounmap(xgi_video_info.mmio_vbase);
3393 iounmap(xgi_video_info.video_vbase);
3394 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
3395 release_mem_region(xgi_video_info.video_base,
3396 xgi_video_info.video_size);
3397 vfree(XGIhw_ext.pjVirtualRomBase);
3398 framebuffer_release(fb_info);
3399 pci_set_drvdata(pdev, NULL);
3402 static struct pci_driver xgifb_driver = {
3404 .id_table = xgifb_pci_table,
3405 .probe = xgifb_probe,
3406 .remove = __devexit_p(xgifb_remove)
3409 XGIINITSTATIC int __init xgifb_init(void)
3411 char *option = NULL;
3413 if (fb_get_options("xgifb", &option))
3415 XGIfb_setup(option);
3417 return pci_register_driver(&xgifb_driver);
3421 module_init(xgifb_init);
3424 /*****************************************************/
3426 /*****************************************************/
3430 static char *mode = NULL;
3431 static int vesa = 0;
3432 static unsigned int rate = 0;
3433 static unsigned int mem = 0;
3434 static char *forcecrt2type = NULL;
3435 static int forcecrt1 = -1;
3436 static int pdc = -1;
3437 static int pdc1 = -1;
3438 static int noypan = -1;
3439 static int nomax = -1;
3440 static int userom = -1;
3441 static int useoem = -1;
3442 static char *tvstandard = NULL;
3443 static int nocrt2rate = 0;
3444 static int scalelcd = -1;
3445 static char *specialtiming = NULL;
3446 static int lvdshl = -1;
3447 static int tvxposoffset = 0, tvyposoffset = 0;
3448 #if !defined(__i386__) && !defined(__x86_64__)
3449 static int resetcard = 0;
3450 static int videoram = 0;
3453 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3454 MODULE_LICENSE("GPL");
3455 MODULE_AUTHOR("XGITECH , Others");
3457 module_param(mem, int, 0);
3458 module_param(noypan, int, 0);
3459 module_param(nomax, int, 0);
3460 module_param(userom, int, 0);
3461 module_param(useoem, int, 0);
3462 module_param(mode, charp, 0);
3463 module_param(vesa, int, 0);
3464 module_param(rate, int, 0);
3465 module_param(forcecrt1, int, 0);
3466 module_param(forcecrt2type, charp, 0);
3467 module_param(scalelcd, int, 0);
3468 module_param(pdc, int, 0);
3469 module_param(pdc1, int, 0);
3470 module_param(specialtiming, charp, 0);
3471 module_param(lvdshl, int, 0);
3472 module_param(tvstandard, charp, 0);
3473 module_param(tvxposoffset, int, 0);
3474 module_param(tvyposoffset, int, 0);
3475 module_param(filter, int, 0);
3476 module_param(nocrt2rate, int, 0);
3477 #if !defined(__i386__) && !defined(__x86_64__)
3478 module_param(resetcard, int, 0);
3479 module_param(videoram, int, 0);
3482 MODULE_PARM_DESC(mem,
3483 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3484 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3485 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3486 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3487 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3488 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3489 "for XFree86 4.x/X.org 6.7 and later.\n");
3491 MODULE_PARM_DESC(noypan,
3492 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3493 "will be performed by redrawing the screen. (default: 0)\n");
3495 MODULE_PARM_DESC(nomax,
3496 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3497 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3498 "this is set to anything other than 0, xgifb will not do this and thereby\n"
3499 "enable the user to positively specify a virtual Y size of the screen using\n"
3500 "fbset. (default: 0)\n");
3502 MODULE_PARM_DESC(mode,
3503 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3504 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3505 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3506 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3508 MODULE_PARM_DESC(vesa,
3509 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3510 "0x117 (default: 0x0103)\n");
3512 MODULE_PARM_DESC(rate,
3513 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3514 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3515 "will be ignored (default: 60)\n");
3517 MODULE_PARM_DESC(forcecrt1,
3518 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
3519 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3520 "0=CRT1 OFF) (default: [autodetected])\n");
3522 MODULE_PARM_DESC(forcecrt2type,
3523 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3524 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3525 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3526 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3527 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3528 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3529 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3530 "depends on the very hardware in use. (default: [autodetected])\n");
3532 MODULE_PARM_DESC(scalelcd,
3533 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3534 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3535 "show black bars around the image, TMDS panels will probably do the scaling\n"
3536 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3538 MODULE_PARM_DESC(pdc,
3539 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3540 "should detect this correctly in most cases; however, sometimes this is not\n"
3541 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3542 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3543 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3544 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3546 MODULE_PARM_DESC(pdc1,
3547 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3548 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3549 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3550 "implemented yet.\n");
3552 MODULE_PARM_DESC(specialtiming,
3553 "\nPlease refer to documentation for more information on this option.\n");
3555 MODULE_PARM_DESC(lvdshl,
3556 "\nPlease refer to documentation for more information on this option.\n");
3558 MODULE_PARM_DESC(tvstandard,
3559 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3560 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3562 MODULE_PARM_DESC(tvxposoffset,
3563 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3566 MODULE_PARM_DESC(tvyposoffset,
3567 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3570 MODULE_PARM_DESC(filter,
3571 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3572 "(Possible values 0-7, default: [no filter])\n");
3574 MODULE_PARM_DESC(nocrt2rate,
3575 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3576 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3578 static int __init xgifb_init_module(void)
3580 printk("\nXGIfb_init_module");
3582 XGIfb_search_mode(mode);
3583 else if (vesa != -1)
3584 XGIfb_search_vesamode(vesa);
3586 return xgifb_init();
3589 static void __exit xgifb_remove_module(void)
3591 pci_unregister_driver(&xgifb_driver);
3592 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3595 module_init(xgifb_init_module);
3596 module_exit(xgifb_remove_module);
3598 #endif /* /MODULE */
3600 EXPORT_SYMBOL(XGI_malloc);
3601 EXPORT_SYMBOL(XGI_free);