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 xgi_video_info.accel = 0;
1191 switch (xgi_video_info.video_bpp) {
1193 xgi_video_info.DstColor = 0x0000;
1194 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1195 xgi_video_info.video_cmap_len = 256;
1196 #if defined(__powerpc__)
1197 inXGIIDXREG(XGICR, 0x4D, cr_data);
1198 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1202 xgi_video_info.DstColor = 0x8000;
1203 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1204 #if defined(__powerpc__)
1205 inXGIIDXREG(XGICR, 0x4D, cr_data);
1206 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1208 xgi_video_info.video_cmap_len = 16;
1211 xgi_video_info.DstColor = 0xC000;
1212 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1213 xgi_video_info.video_cmap_len = 16;
1214 #if defined(__powerpc__)
1215 inXGIIDXREG(XGICR, 0x4D, cr_data);
1216 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1220 xgi_video_info.video_cmap_len = 16;
1221 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1222 xgi_video_info.accel = 0;
1226 XGIfb_bpp_to_var(var); /*update ARGB info*/
1227 DEBUGPRN("End of do_set_var");
1234 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1238 /* printk("Inside pan_var"); */
1240 if (var->xoffset > (var->xres_virtual - var->xres)) {
1241 /* printk("Pan: xo: %d xv %d xr %d\n",
1242 var->xoffset, var->xres_virtual, var->xres); */
1245 if (var->yoffset > (var->yres_virtual - var->yres)) {
1246 /* printk("Pan: yo: %d yv %d yr %d\n",
1247 var->yoffset, var->yres_virtual, var->yres); */
1250 base = var->yoffset * var->xres_virtual + var->xoffset;
1252 /* calculate base bpp dep. */
1253 switch (var->bits_per_pixel) {
1265 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1267 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1268 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1269 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1270 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1271 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1273 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1274 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1275 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1276 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1277 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1278 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1280 /* printk("End of pan_var"); */
1285 void XGI_dispinfo(struct ap_data *rec)
1287 rec->minfo.bpp = xgi_video_info.video_bpp;
1288 rec->minfo.xres = xgi_video_info.video_width;
1289 rec->minfo.yres = xgi_video_info.video_height;
1290 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1291 rec->minfo.v_yres = xgi_video_info.video_vheight;
1292 rec->minfo.org_x = xgi_video_info.org_x;
1293 rec->minfo.org_y = xgi_video_info.org_y;
1294 rec->minfo.vrate = xgi_video_info.refresh_rate;
1295 rec->iobase = xgi_video_info.vga_base - 0x30;
1296 rec->mem_size = xgi_video_info.video_size;
1297 rec->disp_state = xgi_video_info.disp_state;
1298 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1299 rec->hasVB = xgi_video_info.hasVB;
1300 rec->TV_type = xgi_video_info.TV_type;
1301 rec->TV_plug = xgi_video_info.TV_plug;
1302 rec->chip = xgi_video_info.chip;
1305 static int XGIfb_open(struct fb_info *info, int user)
1310 static int XGIfb_release(struct fb_info *info, int user)
1315 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1319 switch (var->bits_per_pixel) {
1333 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1334 unsigned blue, unsigned transp, struct fb_info *info)
1336 if (regno >= XGIfb_get_cmap_len(&info->var))
1339 switch (info->var.bits_per_pixel) {
1341 outXGIREG(XGIDACA, regno);
1342 outXGIREG(XGIDACD, (red >> 10));
1343 outXGIREG(XGIDACD, (green >> 10));
1344 outXGIREG(XGIDACD, (blue >> 10));
1345 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1346 outXGIREG(XGIDAC2A, regno);
1347 outXGIREG(XGIDAC2D, (red >> 8));
1348 outXGIREG(XGIDAC2D, (green >> 8));
1349 outXGIREG(XGIDAC2D, (blue >> 8));
1353 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1354 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1361 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1368 static int XGIfb_set_par(struct fb_info *info)
1372 /* printk("XGIfb: inside set_par\n"); */
1373 err = XGIfb_do_set_var(&info->var, 1, info);
1376 XGIfb_get_fix(&info->fix, -1, info);
1377 /* printk("XGIfb: end of set_par\n"); */
1381 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1383 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1385 unsigned int vtotal = 0;
1386 unsigned int drate = 0, hrate = 0;
1388 int refresh_rate, search_idx;
1390 DEBUGPRN("Inside check_var");
1392 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1393 vtotal = var->upper_margin + var->yres + var->lower_margin
1396 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1397 vtotal = var->upper_margin + var->yres + var->lower_margin
1400 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1401 vtotal = var->upper_margin + (var->yres / 2)
1402 + var->lower_margin + var->vsync_len;
1404 vtotal = var->upper_margin + var->yres + var->lower_margin
1407 if (!(htotal) || !(vtotal))
1408 XGIFAIL("XGIfb: no valid timing data");
1410 if (var->pixclock && htotal && vtotal) {
1411 drate = 1000000000 / var->pixclock;
1412 hrate = (drate * 1000) / htotal;
1413 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1415 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1416 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1417 __func__, var->pixclock, htotal, vtotal,
1418 __func__, drate, hrate, xgi_video_info.refresh_rate);
1420 xgi_video_info.refresh_rate = 60;
1424 if ((var->pixclock) && (htotal)) {
1425 drate = 1E12 / var->pixclock;
1426 hrate = drate / htotal;
1427 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1432 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1433 if ((var->xres == 1024) && (var->yres == 600))
1437 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1438 (XGIbios_mode[search_idx].xres <= var->xres)) {
1439 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1440 (XGIbios_mode[search_idx].yres == var->yres) &&
1441 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1442 if (XGIfb_validate_mode(search_idx) > 0) {
1452 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1453 var->xres, var->yres, var->bits_per_pixel);
1455 while (XGIbios_mode[search_idx].mode_no != 0) {
1457 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1458 (var->yres <= XGIbios_mode[search_idx].yres) &&
1459 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1460 if (XGIfb_validate_mode(search_idx) > 0) {
1468 var->xres = XGIbios_mode[search_idx].xres;
1469 var->yres = XGIbios_mode[search_idx].yres;
1470 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1471 var->xres, var->yres, var->bits_per_pixel);
1474 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1475 var->xres, var->yres, var->bits_per_pixel);
1480 /* TW: TODO: Check the refresh rate */
1482 /* Adapt RGB settings */
1483 XGIfb_bpp_to_var(var);
1485 /* Sanity check for offsets */
1486 if (var->xoffset < 0)
1488 if (var->yoffset < 0)
1492 if (var->xres != var->xres_virtual)
1493 var->xres_virtual = var->xres;
1494 if (var->yres != var->yres_virtual)
1495 var->yres_virtual = var->yres;
1497 /* TW: Now patch yres_virtual if we use panning */
1498 /* May I do this? */
1499 /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1500 /* if (var->yres_virtual <= var->yres) { */
1501 /* TW: Paranoia check */
1502 /* var->yres_virtual = var->yres; */
1506 /* Truncate offsets to maximum if too high */
1507 if (var->xoffset > var->xres_virtual - var->xres)
1508 var->xoffset = var->xres_virtual - var->xres - 1;
1510 if (var->yoffset > var->yres_virtual - var->yres)
1511 var->yoffset = var->yres_virtual - var->yres - 1;
1513 /* Set everything else to 0 */
1514 var->red.msb_right =
1515 var->green.msb_right =
1516 var->blue.msb_right =
1517 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1519 DEBUGPRN("end of check_var");
1524 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1525 struct fb_info *info)
1529 /* printk("\nInside pan_display:\n"); */
1531 if (var->xoffset > (var->xres_virtual - var->xres))
1533 if (var->yoffset > (var->yres_virtual - var->yres))
1536 if (var->vmode & FB_VMODE_YWRAP) {
1537 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1541 if (var->xoffset + info->var.xres > info->var.xres_virtual
1542 || var->yoffset + info->var.yres
1543 > info->var.yres_virtual)
1546 err = XGIfb_pan_var(var);
1550 info->var.xoffset = var->xoffset;
1551 info->var.yoffset = var->yoffset;
1552 if (var->vmode & FB_VMODE_YWRAP)
1553 info->var.vmode |= FB_VMODE_YWRAP;
1555 info->var.vmode &= ~FB_VMODE_YWRAP;
1557 /* printk("End of pan_display\n"); */
1562 static int XGIfb_blank(int blank, struct fb_info *info)
1566 inXGIIDXREG(XGICR, 0x17, reg);
1573 outXGIIDXREG(XGICR, 0x17, reg);
1574 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1575 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1579 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1582 DEBUGPRN("inside ioctl");
1585 if (!capable(CAP_SYS_RAWIO))
1587 XGI_malloc((struct XGI_memreq *) arg);
1590 if (!capable(CAP_SYS_RAWIO))
1592 XGI_free(*(unsigned long *) arg);
1594 case FBIOGET_HWCINFO: {
1595 unsigned long *hwc_offset = (unsigned long *) arg;
1597 if (XGIfb_caps & HW_CURSOR_CAP)
1599 = XGIfb_hwcursor_vbase
1600 - (unsigned long) xgi_video_info.video_vbase;
1606 case FBIOPUT_MODEINFO: {
1607 struct mode_info *x = (struct mode_info *) arg;
1609 xgi_video_info.video_bpp = x->bpp;
1610 xgi_video_info.video_width = x->xres;
1611 xgi_video_info.video_height = x->yres;
1612 xgi_video_info.video_vwidth = x->v_xres;
1613 xgi_video_info.video_vheight = x->v_yres;
1614 xgi_video_info.org_x = x->org_x;
1615 xgi_video_info.org_y = x->org_y;
1616 xgi_video_info.refresh_rate = x->vrate;
1617 xgi_video_info.video_linelength = xgi_video_info.video_vwidth
1618 * (xgi_video_info.video_bpp >> 3);
1619 switch (xgi_video_info.video_bpp) {
1621 xgi_video_info.DstColor = 0x0000;
1622 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1623 xgi_video_info.video_cmap_len = 256;
1626 xgi_video_info.DstColor = 0x8000;
1627 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1628 xgi_video_info.video_cmap_len = 16;
1631 xgi_video_info.DstColor = 0xC000;
1632 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1633 xgi_video_info.video_cmap_len = 16;
1636 xgi_video_info.video_cmap_len = 16;
1637 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1638 xgi_video_info.accel = 0;
1644 case FBIOGET_DISPINFO:
1645 XGI_dispinfo((struct ap_data *) arg);
1647 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1649 struct XGIfb_info *x = (struct XGIfb_info *) arg;
1651 /* x->XGIfb_id = XGIFB_ID; */
1652 x->XGIfb_version = VER_MAJOR;
1653 x->XGIfb_revision = VER_MINOR;
1654 x->XGIfb_patchlevel = VER_LEVEL;
1655 x->chip_id = xgi_video_info.chip_id;
1656 x->memory = xgi_video_info.video_size / 1024;
1657 x->heapstart = xgi_video_info.heapstart / 1024;
1658 x->fbvidmode = XGIfb_mode_no;
1659 x->XGIfb_caps = XGIfb_caps;
1660 x->XGIfb_tqlen = 512; /* yet unused */
1661 x->XGIfb_pcibus = xgi_video_info.pcibus;
1662 x->XGIfb_pcislot = xgi_video_info.pcislot;
1663 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1664 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1665 x->XGIfb_lcda = XGIfb_detectedlcda;
1668 case XGIFB_GET_VBRSTATUS: {
1669 unsigned long *vbrstatus = (unsigned long *) arg;
1670 if (XGIfb_CheckVBRetrace())
1677 } DEBUGPRN("end of ioctl");
1682 /* ----------- FBDev related routines for all series ---------- */
1684 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1685 struct fb_info *info)
1687 DEBUGPRN("inside get_fix");
1688 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1690 strcpy(fix->id, myid);
1692 fix->smem_start = xgi_video_info.video_base;
1694 fix->smem_len = xgi_video_info.video_size;
1696 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1697 if (xgi_video_info.video_size > 0x1000000) {
1698 fix->smem_len = 0xD00000;
1699 } else if (xgi_video_info.video_size > 0x800000)
1700 fix->smem_len = 0x800000;
1702 fix->smem_len = 0x400000;
1704 fix->smem_len = XGIfb_mem * 1024;
1706 fix->type = video_type;
1708 if (xgi_video_info.video_bpp == 8)
1709 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1711 fix->visual = FB_VISUAL_DIRECTCOLOR;
1718 fix->line_length = xgi_video_info.video_linelength;
1719 fix->mmio_start = xgi_video_info.mmio_base;
1720 fix->mmio_len = xgi_video_info.mmio_size;
1721 if (xgi_video_info.chip >= XG40)
1722 fix->accel = FB_ACCEL_XGI_XABRE;
1724 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1726 DEBUGPRN("end of get_fix");
1730 static struct fb_ops XGIfb_ops = {
1731 .owner = THIS_MODULE,
1732 .fb_open = XGIfb_open,
1733 .fb_release = XGIfb_release,
1734 .fb_check_var = XGIfb_check_var,
1735 .fb_set_par = XGIfb_set_par,
1736 .fb_setcolreg = XGIfb_setcolreg,
1738 .fb_pan_display = XGIfb_pan_display,
1740 .fb_blank = XGIfb_blank,
1741 .fb_fillrect = cfb_fillrect,
1742 .fb_copyarea = cfb_copyarea,
1743 .fb_imageblit = cfb_imageblit,
1744 .fb_ioctl = XGIfb_ioctl,
1745 /* .fb_mmap = XGIfb_mmap, */
1748 /* ---------------- Chip generation dependent routines ---------------- */
1750 /* for XGI 315/550/650/740/330 */
1752 static int XGIfb_get_dram_size(void)
1758 /* xorg driver sets 32MB * 1 channel */
1759 if (xgi_video_info.chip == XG27)
1760 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1762 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1763 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1764 case XGI_DRAM_SIZE_1MB:
1765 xgi_video_info.video_size = 0x100000;
1767 case XGI_DRAM_SIZE_2MB:
1768 xgi_video_info.video_size = 0x200000;
1770 case XGI_DRAM_SIZE_4MB:
1771 xgi_video_info.video_size = 0x400000;
1773 case XGI_DRAM_SIZE_8MB:
1774 xgi_video_info.video_size = 0x800000;
1776 case XGI_DRAM_SIZE_16MB:
1777 xgi_video_info.video_size = 0x1000000;
1779 case XGI_DRAM_SIZE_32MB:
1780 xgi_video_info.video_size = 0x2000000;
1782 case XGI_DRAM_SIZE_64MB:
1783 xgi_video_info.video_size = 0x4000000;
1785 case XGI_DRAM_SIZE_128MB:
1786 xgi_video_info.video_size = 0x8000000;
1788 case XGI_DRAM_SIZE_256MB:
1789 xgi_video_info.video_size = 0x10000000;
1795 tmp = (reg & 0x0c) >> 2;
1796 switch (xgi_video_info.chip) {
1832 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1833 /* PLiad fixed for benchmarking and fb set */
1834 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1835 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1837 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1838 xgi_video_info.video_size, ChannelNum);
1843 static void XGIfb_detect_VB(void)
1847 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1849 switch (xgi_video_info.hasVB) {
1850 case HASVB_LVDS_CHRONTEL:
1851 case HASVB_CHRONTEL:
1855 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1859 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1861 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1870 if (XGIfb_crt2type != -1)
1871 /* TW: Override with option */
1872 xgi_video_info.disp_state = XGIfb_crt2type;
1873 else if (cr32 & XGI_VB_TV)
1874 xgi_video_info.disp_state = DISPTYPE_TV;
1875 else if (cr32 & XGI_VB_LCD)
1876 xgi_video_info.disp_state = DISPTYPE_LCD;
1877 else if (cr32 & XGI_VB_CRT2)
1878 xgi_video_info.disp_state = DISPTYPE_CRT2;
1880 xgi_video_info.disp_state = 0;
1882 if (XGIfb_tvplug != -1)
1883 /* PR/TW: Override with option */
1884 xgi_video_info.TV_plug = XGIfb_tvplug;
1885 else if (cr32 & XGI_VB_HIVISION) {
1886 xgi_video_info.TV_type = TVMODE_HIVISION;
1887 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1888 } else if (cr32 & XGI_VB_SVIDEO)
1889 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1890 else if (cr32 & XGI_VB_COMPOSITE)
1891 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1892 else if (cr32 & XGI_VB_SCART)
1893 xgi_video_info.TV_plug = TVPLUG_SCART;
1895 if (xgi_video_info.TV_type == 0) {
1896 /* TW: PAL/NTSC changed for 650 */
1897 if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
1900 inXGIIDXREG(XGICR, 0x38, temp);
1902 xgi_video_info.TV_type = TVMODE_PAL;
1904 xgi_video_info.TV_type = TVMODE_NTSC;
1908 inXGIIDXREG(XGICR, 0x79, temp);
1910 xgi_video_info.TV_type = TVMODE_PAL;
1912 xgi_video_info.TV_type = TVMODE_NTSC;
1916 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1917 if (XGIfb_forcecrt1 != -1) {
1918 if (XGIfb_forcecrt1)
1925 static void XGIfb_get_VB_type(void)
1929 if (!XGIfb_has_VB()) {
1930 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1931 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1932 case XGI310_EXTERNAL_CHIP_LVDS:
1933 xgi_video_info.hasVB = HASVB_LVDS;
1935 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1936 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1944 static int XGIfb_has_VB(void)
1948 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1949 switch (vb_chipid) {
1951 xgi_video_info.hasVB = HASVB_301;
1954 xgi_video_info.hasVB = HASVB_302;
1957 xgi_video_info.hasVB = HASVB_NONE;
1963 /* ------------------ Sensing routines ------------------ */
1965 /* TW: Determine and detect attached devices on XGI30x */
1966 int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1970 outXGIIDXREG(XGIPART4, 0x11, tempbl);
1971 temp = tempbh | tempcl;
1972 setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1973 for (i = 0; i < 10; i++)
1974 XGI_LongWait(&XGI_Pr);
1976 inXGIIDXREG(XGIPART4, 0x03, temp);
1982 void XGI_Sense30x(void)
1985 u8 testsvhs_tempbl, testsvhs_tempbh;
1986 u8 testsvhs_tempcl, testsvhs_tempch;
1987 u8 testcvbs_tempbl, testcvbs_tempbh;
1988 u8 testcvbs_tempcl, testcvbs_tempch;
1989 u8 testvga2_tempbl, testvga2_tempbh;
1990 u8 testvga2_tempcl, testvga2_tempch;
1993 inXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
1994 outXGIIDXREG(XGIPART4, 0x0d, (backupP4_0d | 0x04));
1996 testvga2_tempbh = 0x00;
1997 testvga2_tempbl = 0xd1;
1998 testsvhs_tempbh = 0x00;
1999 testsvhs_tempbl = 0xb9;
2000 testcvbs_tempbh = 0x00;
2001 testcvbs_tempbl = 0xb3;
2002 if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
2004 testvga2_tempbh = 0x01;
2005 testvga2_tempbl = 0x90;
2006 testsvhs_tempbh = 0x01;
2007 testsvhs_tempbl = 0x6b;
2008 testcvbs_tempbh = 0x01;
2009 testcvbs_tempbl = 0x74;
2010 if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
2011 || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2012 testvga2_tempbh = 0x00;
2013 testvga2_tempbl = 0x00;
2014 testsvhs_tempbh = 0x02;
2015 testsvhs_tempbl = 0x00;
2016 testcvbs_tempbh = 0x01;
2017 testcvbs_tempbl = 0x00;
2020 if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
2022 inXGIIDXREG(XGIPART4, 0x01, myflag);
2023 if (myflag & 0x04) {
2024 testvga2_tempbh = 0x00;
2025 testvga2_tempbl = 0xfd;
2026 testsvhs_tempbh = 0x00;
2027 testsvhs_tempbl = 0xdd;
2028 testcvbs_tempbh = 0x00;
2029 testcvbs_tempbl = 0xee;
2032 if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
2033 == VB_CHIP_302LV)) {
2034 testvga2_tempbh = 0x00;
2035 testvga2_tempbl = 0x00;
2036 testvga2_tempch = 0x00;
2037 testvga2_tempcl = 0x00;
2038 testsvhs_tempch = 0x04;
2039 testsvhs_tempcl = 0x08;
2040 testcvbs_tempch = 0x08;
2041 testcvbs_tempcl = 0x08;
2043 testvga2_tempch = 0x0e;
2044 testvga2_tempcl = 0x08;
2045 testsvhs_tempch = 0x06;
2046 testsvhs_tempcl = 0x04;
2047 testcvbs_tempch = 0x08;
2048 testcvbs_tempcl = 0x04;
2051 if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
2052 || testvga2_tempbl) {
2053 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2054 testvga2_tempcl, testvga2_tempch);
2056 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2057 orXGIIDXREG(XGICR, 0x32, 0x10);
2061 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
2064 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2065 /* TW: So we can be sure that there IS a SVHS output */
2066 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2067 orXGIIDXREG(XGICR, 0x32, 0x02);
2071 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2072 testcvbs_tempcl, testcvbs_tempch);
2074 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2075 /* TW: So we can be sure that there IS a CVBS output */
2076 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2077 orXGIIDXREG(XGICR, 0x32, 0x01);
2080 XGIDoSense(0, 0, 0, 0);
2082 outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
2085 /* ------------------------ Heap routines -------------------------- */
2087 static int XGIfb_heap_init(void)
2092 int agp_enabled = 1;
2094 unsigned long *cmdq_baseport = NULL;
2095 unsigned long *read_port = NULL;
2096 unsigned long *write_port = NULL;
2097 XGI_CMDTYPE cmd_type;
2099 struct agp_kern_info *agp_info;
2100 struct agp_memory *agp;
2104 /* TW: The heap start is either set manually using the "mem" parameter, or
2105 * defaults as follows:
2106 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2107 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2108 * -) If 4MB or less is available, let it start at 4MB.
2109 * This is for avoiding a clash with X driver which uses the beginning
2110 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2112 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2113 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2115 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
2116 if (xgi_video_info.video_size > 0x1000000)
2117 xgi_video_info.heapstart = 0xD00000;
2118 else if (xgi_video_info.video_size > 0x800000)
2119 xgi_video_info.heapstart = 0x800000;
2121 xgi_video_info.heapstart = 0x400000;
2123 xgi_video_info.heapstart = XGIfb_mem * 1024;
2125 XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
2126 + xgi_video_info.heapstart);
2127 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2128 (int)(xgi_video_info.heapstart / 1024));
2130 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
2131 + xgi_video_info.video_size;
2132 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2134 /* TW: Now initialize the 310 series' command queue mode.
2135 * On 310/325, there are three queue modes available which
2136 * are chosen by setting bits 7:5 in SR26:
2137 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2138 * track of the queue, the FIFO, command parsing and so
2139 * on. This is the one comparable to the 300 series.
2140 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2141 * have to do queue management himself. Register 0x85c4 will
2142 * hold the location of the next free queue slot, 0x85c8
2143 * is the "queue read pointer" whose way of working is
2144 * unknown to me. Anyway, this mode would require a
2145 * translation of the MMIO commands to some kind of
2146 * accelerator assembly and writing these commands
2147 * to the memory location pointed to by 0x85c4.
2148 * We will not use this, as nobody knows how this
2149 * "assembly" works, and as it would require a complete
2150 * re-write of the accelerator code.
2151 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2152 * queue in AGP memory space.
2154 * SR26 bit 4 is called "Bypass H/W queue".
2155 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2156 * SR26 bit 0 resets the queue
2157 * Size of queue memory is encoded in bits 3:2 like this:
2162 * The queue location is to be written to 0x85C0.
2165 cmdq_baseport = (unsigned long *) (xgi_video_info.mmio_vbase
2166 + MMIO_QUEUE_PHYBASE);
2167 write_port = (unsigned long *) (xgi_video_info.mmio_vbase
2168 + MMIO_QUEUE_WRITEPORT);
2169 read_port = (unsigned long *) (xgi_video_info.mmio_vbase
2170 + MMIO_QUEUE_READPORT);
2172 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2174 agp_size = COMMAND_QUEUE_AREA_SIZE;
2177 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2178 agp_info = vzalloc(sizeof(*agp_info));
2179 agp_copy_info(agp_info);
2181 agp_backend_acquire();
2183 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
2186 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2189 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2190 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2191 /* TODO: Free AGP memory here */
2202 /* TW: Now select the queue mode */
2204 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2205 cmd_type = AGP_CMD_QUEUE;
2206 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2207 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2208 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2209 cmd_type = VM_CMD_QUEUE;
2210 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2212 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2213 cmd_type = MMIO_CMD;
2218 temp = XGI_CMD_QUEUE_SIZE_512k;
2221 temp = XGI_CMD_QUEUE_SIZE_1M;
2224 temp = XGI_CMD_QUEUE_SIZE_2M;
2227 temp = XGI_CMD_QUEUE_SIZE_4M;
2234 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2235 agp_info->aper_base, agp->physical, agp_size/1024);
2237 agp_phys = agp_info->aper_base + agp->physical;
2239 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2240 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2242 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2244 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2246 *write_port = *read_port;
2248 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2249 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2251 *cmdq_baseport = agp_phys;
2253 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2258 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2259 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2261 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2263 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2265 *write_port = *read_port;
2267 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2268 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2270 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2272 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2274 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2275 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2280 /* printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); */
2281 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2282 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2283 * enough. Reserve memory in any way.
2285 /* FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; */
2286 /* FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; */
2288 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); */
2289 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); */
2291 /* FIXME *write_port = *read_port; */
2293 /* FIXME *//* TW: Set Auto_Correction bit */
2294 /* FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); */
2295 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); */
2297 /* FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; */
2299 /* FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; */
2301 /* FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", */
2302 /* FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); */
2306 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2307 top of the videoRAM, right below the TB memory area (if used). */
2308 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2309 XGIfb_heap_end -= XGIfb_hwcursor_size;
2310 XGIfb_heap_size -= XGIfb_hwcursor_size;
2311 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2313 XGIfb_caps |= HW_CURSOR_CAP;
2315 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2316 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2319 XGIfb_heap.poha_chain = NULL;
2320 XGIfb_heap.poh_freelist = NULL;
2322 poh = XGIfb_poh_new_node();
2327 poh->poh_next = &XGIfb_heap.oh_free;
2328 poh->poh_prev = &XGIfb_heap.oh_free;
2329 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2330 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2332 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2333 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2334 (unsigned int) poh->size / 1024);
2336 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2337 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2339 XGIfb_heap.oh_free.poh_next = poh;
2340 XGIfb_heap.oh_free.poh_prev = poh;
2341 XGIfb_heap.oh_free.size = 0;
2342 XGIfb_heap.max_freesize = poh->size;
2344 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2345 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2346 XGIfb_heap.oh_used.size = SENTINEL;
2351 static XGI_OH *XGIfb_poh_new_node(void)
2358 if (XGIfb_heap.poh_freelist == NULL) {
2359 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2363 poha->poha_next = XGIfb_heap.poha_chain;
2364 XGIfb_heap.poha_chain = poha;
2366 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
2369 poh = &poha->aoh[0];
2370 for (i = cOhs - 1; i != 0; i--) {
2371 poh->poh_next = poh + 1;
2375 poh->poh_next = NULL;
2376 XGIfb_heap.poh_freelist = &poha->aoh[0];
2379 poh = XGIfb_heap.poh_freelist;
2380 XGIfb_heap.poh_freelist = poh->poh_next;
2385 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2391 if (size > XGIfb_heap.max_freesize) {
2392 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2393 (unsigned int) size / 1024);
2397 pohThis = XGIfb_heap.oh_free.poh_next;
2399 while (pohThis != &XGIfb_heap.oh_free) {
2400 if (size <= pohThis->size) {
2404 pohThis = pohThis->poh_next;
2408 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2409 (unsigned int) size / 1024);
2413 if (size == pohThis->size) {
2415 XGIfb_delete_node(pohThis);
2417 pohRoot = XGIfb_poh_new_node();
2419 if (pohRoot == NULL)
2422 pohRoot->offset = pohThis->offset;
2423 pohRoot->size = size;
2425 pohThis->offset += size;
2426 pohThis->size -= size;
2429 XGIfb_heap.max_freesize -= size;
2431 pohThis = &XGIfb_heap.oh_used;
2432 XGIfb_insert_node(pohThis, pohRoot);
2437 static void XGIfb_delete_node(XGI_OH *poh)
2442 poh_prev = poh->poh_prev;
2443 poh_next = poh->poh_next;
2445 poh_prev->poh_next = poh_next;
2446 poh_next->poh_prev = poh_prev;
2450 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2454 pohTemp = pohList->poh_next;
2456 pohList->poh_next = poh;
2457 pohTemp->poh_prev = poh;
2459 poh->poh_prev = pohList;
2460 poh->poh_next = pohTemp;
2463 static XGI_OH *XGIfb_poh_free(unsigned long base)
2469 unsigned long ulUpper;
2470 unsigned long ulLower;
2473 poh_freed = XGIfb_heap.oh_used.poh_next;
2475 while (poh_freed != &XGIfb_heap.oh_used) {
2476 if (poh_freed->offset == base) {
2481 poh_freed = poh_freed->poh_next;
2487 XGIfb_heap.max_freesize += poh_freed->size;
2489 poh_prev = poh_next = NULL;
2490 ulUpper = poh_freed->offset + poh_freed->size;
2491 ulLower = poh_freed->offset;
2493 pohThis = XGIfb_heap.oh_free.poh_next;
2495 while (pohThis != &XGIfb_heap.oh_free) {
2496 if (pohThis->offset == ulUpper)
2498 else if ((pohThis->offset + pohThis->size) == ulLower)
2501 pohThis = pohThis->poh_next;
2504 XGIfb_delete_node(poh_freed);
2506 if (poh_prev && poh_next) {
2507 poh_prev->size += (poh_freed->size + poh_next->size);
2508 XGIfb_delete_node(poh_next);
2509 XGIfb_free_node(poh_freed);
2510 XGIfb_free_node(poh_next);
2515 poh_prev->size += poh_freed->size;
2516 XGIfb_free_node(poh_freed);
2521 poh_next->size += poh_freed->size;
2522 poh_next->offset = poh_freed->offset;
2523 XGIfb_free_node(poh_freed);
2527 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2532 static void XGIfb_free_node(XGI_OH *poh)
2537 poh->poh_next = XGIfb_heap.poh_freelist;
2538 XGIfb_heap.poh_freelist = poh;
2542 void XGI_malloc(struct XGI_memreq *req)
2546 poh = XGIfb_poh_allocate(req->size);
2551 DPRINTK("XGIfb: Video RAM allocation failed\n");
2553 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2554 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2556 req->offset = poh->offset;
2557 req->size = poh->size;
2562 void XGI_free(unsigned long base)
2566 poh = XGIfb_poh_free(base);
2569 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2570 (unsigned int) base);
2574 /* --------------------- SetMode routines ------------------------- */
2576 static void XGIfb_pre_setmode(void)
2578 u8 cr30 = 0, cr31 = 0;
2580 inXGIIDXREG(XGICR, 0x31, cr31);
2583 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2585 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2586 cr31 |= XGI_DRIVER_MODE;
2589 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2590 cr31 |= XGI_DRIVER_MODE;
2593 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2594 cr30 = (XGI_VB_OUTPUT_HIVISION
2595 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2596 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2597 cr30 = (XGI_VB_OUTPUT_SVIDEO
2598 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2599 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2600 cr30 = (XGI_VB_OUTPUT_COMPOSITE
2601 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2602 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2603 cr30 = (XGI_VB_OUTPUT_SCART
2604 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2605 cr31 |= XGI_DRIVER_MODE;
2607 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2612 default: /* disable CRT2 */
2614 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2617 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2618 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2619 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2621 if (xgi_video_info.accel)
2626 static void XGIfb_post_setmode(void)
2629 unsigned char doit = 1;
2631 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2632 outXGIIDXREG(XGICR, 0x13, 0x00);
2633 setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
2636 if (xgi_video_info.video_bpp == 8) {
2637 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2638 if ((xgi_video_info.hasVB == HASVB_LVDS)
2639 || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2642 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2643 if (xgi_video_info.disp_state & DISPTYPE_LCD)
2647 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2648 if (xgi_video_info.hasVB != HASVB_NONE) {
2649 inXGIIDXREG(XGIPART1, 0x00, reg);
2651 if ((reg & 0x50) == 0x10)
2658 inXGIIDXREG(XGICR, 0x17, reg);
2659 if ((XGIfb_crt1off) && (doit))
2663 outXGIIDXREG(XGICR, 0x17, reg);
2665 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2667 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
2670 inXGIIDXREG(XGIPART4, 0x01, reg);
2672 if (reg < 0xB0) { /* Set filter for XGI301 */
2674 switch (xgi_video_info.video_width) {
2676 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2679 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2682 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2685 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2692 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2694 if (xgi_video_info.TV_type == TVMODE_NTSC) {
2696 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2698 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2700 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2702 } else if (xgi_video_info.TV_plug
2703 == TVPLUG_COMPOSITE) {
2705 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2707 switch (xgi_video_info.video_width) {
2709 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2710 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2711 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2712 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2715 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2716 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2717 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2718 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2721 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2722 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2723 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2724 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2729 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2731 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2733 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2735 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2737 } else if (xgi_video_info.TV_plug
2738 == TVPLUG_COMPOSITE) {
2740 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2742 switch (xgi_video_info.video_width) {
2744 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2745 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2746 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2747 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2750 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2751 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2752 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2753 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2756 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2757 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2758 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2759 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2765 if ((filter >= 0) && (filter <= 7)) {
2766 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2767 XGI_TV_filter[filter_tb].filter[filter][0],
2768 XGI_TV_filter[filter_tb].filter[filter][1],
2769 XGI_TV_filter[filter_tb].filter[filter][2],
2770 XGI_TV_filter[filter_tb].filter[filter][3]
2775 (XGI_TV_filter[filter_tb].filter[filter][0]));
2779 (XGI_TV_filter[filter_tb].filter[filter][1]));
2783 (XGI_TV_filter[filter_tb].filter[filter][2]));
2787 (XGI_TV_filter[filter_tb].filter[filter][3]));
2796 XGIINITSTATIC int __init XGIfb_setup(char *options)
2800 xgi_video_info.refresh_rate = 0;
2802 printk(KERN_INFO "XGIfb: Options %s\n", options);
2804 if (!options || !*options)
2807 while ((this_opt = strsep(&options, ",")) != NULL) {
2812 if (!strncmp(this_opt, "mode:", 5)) {
2813 XGIfb_search_mode(this_opt + 5);
2814 } else if (!strncmp(this_opt, "vesa:", 5)) {
2815 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2816 } else if (!strncmp(this_opt, "mode:", 5)) {
2817 XGIfb_search_mode(this_opt + 5);
2818 } else if (!strncmp(this_opt, "vesa:", 5)) {
2819 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2820 } else if (!strncmp(this_opt, "vrate:", 6)) {
2821 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2822 } else if (!strncmp(this_opt, "rate:", 5)) {
2823 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2824 } else if (!strncmp(this_opt, "off", 3)) {
2826 } else if (!strncmp(this_opt, "crt1off", 7)) {
2828 } else if (!strncmp(this_opt, "filter:", 7)) {
2829 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2830 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2831 XGIfb_search_crt2type(this_opt + 14);
2832 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2833 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2834 } else if (!strncmp(this_opt, "tvmode:", 7)) {
2835 XGIfb_search_tvstd(this_opt + 7);
2836 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2837 XGIfb_search_tvstd(this_opt + 7);
2838 } else if (!strncmp(this_opt, "mem:", 4)) {
2839 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2840 } else if (!strncmp(this_opt, "dstn", 4)) {
2842 /* TW: DSTN overrules forcecrt2type */
2843 XGIfb_crt2type = DISPTYPE_LCD;
2844 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2845 XGIfb_search_queuemode(this_opt + 10);
2846 } else if (!strncmp(this_opt, "pdc:", 4)) {
2847 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2848 if (XGIfb_pdc & ~0x3c) {
2849 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2852 } else if (!strncmp(this_opt, "noypan", 6)) {
2854 } else if (!strncmp(this_opt, "userom:", 7)) {
2855 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2856 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2857 /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2859 XGIfb_search_mode(this_opt);
2860 /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2863 /* TW: Acceleration only with MMIO mode */
2864 if ((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2867 /* TW: Panning only with acceleration */
2871 printk("\nxgifb: outa xgifb_setup 3450");
2875 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
2877 void __iomem *rom_address;
2878 unsigned char *rom_copy;
2881 rom_address = pci_map_rom(dev, &rom_size);
2882 if (rom_address == NULL)
2885 rom_copy = vzalloc(XGIFB_ROM_SIZE);
2886 if (rom_copy == NULL)
2889 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
2890 memcpy_fromio(rom_copy, rom_address, rom_size);
2893 pci_unmap_rom(dev, rom_address);
2897 static int __devinit xgifb_probe(struct pci_dev *pdev,
2898 const struct pci_device_id *ent)
2908 XGIfb_registered = 0;
2910 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2911 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2915 xgi_video_info.chip_id = pdev->device;
2916 pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2917 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2918 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2919 XGIvga_enabled = reg16 & 0x01;
2921 xgi_video_info.pcibus = pdev->bus->number;
2922 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2923 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2924 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2925 xgi_video_info.subsysdevice = pdev->subsystem_device;
2927 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2928 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2929 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2930 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2931 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2932 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2933 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2934 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2936 if (pci_enable_device(pdev)) {
2941 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2943 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2944 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2946 if (reg1 != 0xa1) { /*I/O error */
2947 printk("\nXGIfb: I/O error!!!");
2952 switch (xgi_video_info.chip_id) {
2953 case PCI_DEVICE_ID_XG_20:
2954 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2955 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2956 if (CR48&GPIOG_READ)
2957 xgi_video_info.chip = XG21;
2959 xgi_video_info.chip = XG20;
2960 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2961 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2963 case PCI_DEVICE_ID_XG_40:
2964 xgi_video_info.chip = XG40;
2965 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2966 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2968 case PCI_DEVICE_ID_XG_41:
2969 xgi_video_info.chip = XG41;
2970 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2971 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2973 case PCI_DEVICE_ID_XG_42:
2974 xgi_video_info.chip = XG42;
2975 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2976 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2978 case PCI_DEVICE_ID_XG_27:
2979 xgi_video_info.chip = XG27;
2980 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2981 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2988 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
2989 XGIhw_ext.jChipType = xgi_video_info.chip;
2991 switch (xgi_video_info.chip) {
2999 XGIhw_ext.bIntegratedMMEnabled = 1;
3005 XGIhw_ext.pDevice = NULL;
3006 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
3007 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
3008 if (XGIhw_ext.pjVirtualRomBase)
3009 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
3011 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3013 XGIhw_ext.pjVirtualRomBase = NULL;
3014 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3016 XGIhw_ext.pjCustomizedROMImage = NULL;
3017 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3018 /* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
3019 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3021 if (!XGIvga_enabled) {
3022 /* Mapping Max FB Size for 315 Init */
3023 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3024 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3026 printk("XGIfb: XGIInit() ...");
3027 /* XGIInitNewt for LINUXBIOS only */
3028 if (XGIInitNew(&XGIhw_ext))
3034 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3040 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3041 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3043 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3045 /* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
3046 /* Set SR13 ,14 temporarily for UDtech */
3047 outXGIIDXREG(XGISR, 0x13, 0x45);
3048 outXGIIDXREG(XGISR, 0x14, 0x51);
3053 if (XGIfb_get_dram_size()) {
3054 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3059 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3060 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3061 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3062 /* Enable 2D accelerator engine */
3063 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3066 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3068 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
3069 printk("unable request memory size %x", xgi_video_info.video_size);
3070 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3071 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3076 if (!request_mem_region(xgi_video_info.mmio_base,
3077 xgi_video_info.mmio_size,
3079 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3084 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3085 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3086 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
3087 xgi_video_info.mmio_size);
3089 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3090 xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
3092 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3093 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
3094 xgi_video_info.mmio_size / 1024);
3095 printk("XGIfb: XGIInitNew() ...");
3096 if (XGIInitNew(&XGIhw_ext))
3101 if (XGIfb_heap_init())
3102 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3104 xgi_video_info.mtrr = (unsigned int) 0;
3106 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3107 xgi_video_info.hasVB = HASVB_NONE;
3108 if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
3109 xgi_video_info.hasVB = HASVB_NONE;
3110 } else if (xgi_video_info.chip == XG21) {
3111 inXGIIDXREG(XGICR, 0x38, CR38);
3112 if ((CR38&0xE0) == 0xC0) {
3113 xgi_video_info.disp_state = DISPTYPE_LCD;
3114 if (!XGIfb_GetXG21LVDSData()) {
3116 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3117 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3118 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3119 XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
3123 } else if ((CR38&0xE0) == 0x60) {
3124 xgi_video_info.hasVB = HASVB_CHRONTEL;
3126 xgi_video_info.hasVB = HASVB_NONE;
3129 XGIfb_get_VB_type();
3132 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3134 XGIhw_ext.ulExternalChip = 0;
3136 switch (xgi_video_info.hasVB) {
3138 inXGIIDXREG(XGIPART4, 0x01, reg);
3140 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3141 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3142 } else if (reg >= 0xD0) {
3143 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3144 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
3146 /* else if (reg >= 0xB0) {
3147 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3148 inXGIIDXREG(XGIPART4, 0x23, reg1);
3149 printk("XGIfb: XGI301B bridge detected\n");
3152 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3153 printk("XGIfb: XGI301 bridge detected\n");
3157 inXGIIDXREG(XGIPART4, 0x01, reg);
3159 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3160 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3161 } else if (reg >= 0xD0) {
3162 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3163 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3164 } else if (reg >= 0xB0) {
3165 inXGIIDXREG(XGIPART4, 0x23, reg1);
3167 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3170 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3171 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3175 XGIhw_ext.ulExternalChip = 0x1;
3176 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3178 case HASVB_TRUMPION:
3179 XGIhw_ext.ulExternalChip = 0x2;
3180 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3182 case HASVB_CHRONTEL:
3183 XGIhw_ext.ulExternalChip = 0x4;
3184 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3186 case HASVB_LVDS_CHRONTEL:
3187 XGIhw_ext.ulExternalChip = 0x5;
3188 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3191 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3195 if (xgi_video_info.hasVB != HASVB_NONE)
3198 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3200 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3202 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3204 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3207 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3209 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3211 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3215 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3219 XGIfb_detectedpdc = 0;
3221 XGIfb_detectedlcda = 0xff;
3224 /* TW: Try to find about LCDA */
3226 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3227 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3228 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
3230 inXGIIDXREG(XGICR, 0x34, tmp);
3232 /* Currently on LCDA? (Some BIOSes leave CR38) */
3233 inXGIIDXREG(XGICR, 0x38, tmp);
3234 if ((tmp & 0x03) == 0x03) {
3235 /* XGI_Pr.XGI_UseLCDA = 1; */
3237 /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
3238 inXGIIDXREG(XGICR, 0x35, tmp);
3240 /* XGI_Pr.XGI_UseLCDA = 1; */
3242 inXGIIDXREG(XGICR, 0x30, tmp);
3244 inXGIIDXREG(XGIPART1, 0x13, tmp);
3246 /* XGI_Pr.XGI_UseLCDA = 1; */
3257 if (xgifb_mode_idx >= 0)
3258 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3260 if (xgifb_mode_idx < 0) {
3261 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3263 xgifb_mode_idx = DEFAULT_LCDMODE;
3264 if (xgi_video_info.chip == XG21)
3265 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3268 xgifb_mode_idx = DEFAULT_TVMODE;
3271 xgifb_mode_idx = DEFAULT_MODE;
3276 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3278 if (xgi_video_info.refresh_rate == 0)
3279 xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
3280 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
3281 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3282 xgi_video_info.refresh_rate = 60;
3285 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3286 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3287 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3288 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3289 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3290 switch (xgi_video_info.video_bpp) {
3292 xgi_video_info.DstColor = 0x0000;
3293 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3294 xgi_video_info.video_cmap_len = 256;
3297 xgi_video_info.DstColor = 0x8000;
3298 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3299 xgi_video_info.video_cmap_len = 16;
3302 xgi_video_info.DstColor = 0xC000;
3303 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3304 xgi_video_info.video_cmap_len = 16;
3307 xgi_video_info.video_cmap_len = 16;
3308 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3312 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3313 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3314 xgi_video_info.refresh_rate);
3316 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3317 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3318 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3320 XGIfb_bpp_to_var(&default_var);
3322 default_var.pixclock = (u32) (1000000000 /
3323 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3324 XGIfb_mode_no, XGIfb_rate_idx));
3326 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3327 XGIfb_mode_no, XGIfb_rate_idx,
3328 &default_var.left_margin, &default_var.right_margin,
3329 &default_var.upper_margin, &default_var.lower_margin,
3330 &default_var.hsync_len, &default_var.vsync_len,
3331 &default_var.sync, &default_var.vmode)) {
3333 if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3334 default_var.yres <<= 1;
3335 default_var.yres_virtual <<= 1;
3336 } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3337 default_var.pixclock >>= 1;
3338 default_var.yres >>= 1;
3339 default_var.yres_virtual >>= 1;
3344 xgi_video_info.accel = 0;
3346 fb_info->flags = FBINFO_FLAG_DEFAULT;
3347 fb_info->var = default_var;
3348 fb_info->fix = XGIfb_fix;
3349 fb_info->par = &xgi_video_info;
3350 fb_info->screen_base = xgi_video_info.video_vbase;
3351 fb_info->fbops = &XGIfb_ops;
3352 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3353 fb_info->pseudo_palette = pseudo_palette;
3355 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3358 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3359 (unsigned int) xgi_video_info.video_size,
3360 MTRR_TYPE_WRCOMB, 1);
3361 if (xgi_video_info.mtrr)
3362 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3365 if (register_framebuffer(fb_info) < 0) {
3370 XGIfb_registered = 1;
3372 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3373 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3382 iounmap(xgi_video_info.mmio_vbase);
3383 iounmap(xgi_video_info.video_vbase);
3384 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
3386 release_mem_region(xgi_video_info.video_base,
3387 xgi_video_info.video_size);
3389 vfree(XGIhw_ext.pjVirtualRomBase);
3390 framebuffer_release(fb_info);
3394 /*****************************************************/
3395 /* PCI DEVICE HANDLING */
3396 /*****************************************************/
3398 static void __devexit xgifb_remove(struct pci_dev *pdev)
3400 unregister_framebuffer(fb_info);
3401 iounmap(xgi_video_info.mmio_vbase);
3402 iounmap(xgi_video_info.video_vbase);
3403 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
3404 release_mem_region(xgi_video_info.video_base,
3405 xgi_video_info.video_size);
3406 vfree(XGIhw_ext.pjVirtualRomBase);
3407 framebuffer_release(fb_info);
3408 pci_set_drvdata(pdev, NULL);
3411 static struct pci_driver xgifb_driver = {
3413 .id_table = xgifb_pci_table,
3414 .probe = xgifb_probe,
3415 .remove = __devexit_p(xgifb_remove)
3418 XGIINITSTATIC int __init xgifb_init(void)
3420 char *option = NULL;
3422 if (fb_get_options("xgifb", &option))
3424 XGIfb_setup(option);
3426 return pci_register_driver(&xgifb_driver);
3430 module_init(xgifb_init);
3433 /*****************************************************/
3435 /*****************************************************/
3439 static char *mode = NULL;
3440 static int vesa = 0;
3441 static unsigned int rate = 0;
3442 static unsigned int mem = 0;
3443 static char *forcecrt2type = NULL;
3444 static int forcecrt1 = -1;
3445 static int pdc = -1;
3446 static int pdc1 = -1;
3447 static int noaccel = -1;
3448 static int noypan = -1;
3449 static int nomax = -1;
3450 static int userom = -1;
3451 static int useoem = -1;
3452 static char *tvstandard = NULL;
3453 static int nocrt2rate = 0;
3454 static int scalelcd = -1;
3455 static char *specialtiming = NULL;
3456 static int lvdshl = -1;
3457 static int tvxposoffset = 0, tvyposoffset = 0;
3458 #if !defined(__i386__) && !defined(__x86_64__)
3459 static int resetcard = 0;
3460 static int videoram = 0;
3463 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3464 MODULE_LICENSE("GPL");
3465 MODULE_AUTHOR("XGITECH , Others");
3467 module_param(mem, int, 0);
3468 module_param(noaccel, int, 0);
3469 module_param(noypan, int, 0);
3470 module_param(nomax, int, 0);
3471 module_param(userom, int, 0);
3472 module_param(useoem, int, 0);
3473 module_param(mode, charp, 0);
3474 module_param(vesa, int, 0);
3475 module_param(rate, int, 0);
3476 module_param(forcecrt1, int, 0);
3477 module_param(forcecrt2type, charp, 0);
3478 module_param(scalelcd, int, 0);
3479 module_param(pdc, int, 0);
3480 module_param(pdc1, int, 0);
3481 module_param(specialtiming, charp, 0);
3482 module_param(lvdshl, int, 0);
3483 module_param(tvstandard, charp, 0);
3484 module_param(tvxposoffset, int, 0);
3485 module_param(tvyposoffset, int, 0);
3486 module_param(filter, int, 0);
3487 module_param(nocrt2rate, int, 0);
3488 #if !defined(__i386__) && !defined(__x86_64__)
3489 module_param(resetcard, int, 0);
3490 module_param(videoram, int, 0);
3493 MODULE_PARM_DESC(mem,
3494 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3495 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3496 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3497 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3498 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3499 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3500 "for XFree86 4.x/X.org 6.7 and later.\n");
3502 MODULE_PARM_DESC(noaccel,
3503 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3506 MODULE_PARM_DESC(noypan,
3507 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3508 "will be performed by redrawing the screen. (default: 0)\n");
3510 MODULE_PARM_DESC(nomax,
3511 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3512 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3513 "this is set to anything other than 0, xgifb will not do this and thereby\n"
3514 "enable the user to positively specify a virtual Y size of the screen using\n"
3515 "fbset. (default: 0)\n");
3517 MODULE_PARM_DESC(mode,
3518 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3519 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3520 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3521 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3523 MODULE_PARM_DESC(vesa,
3524 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3525 "0x117 (default: 0x0103)\n");
3527 MODULE_PARM_DESC(rate,
3528 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3529 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3530 "will be ignored (default: 60)\n");
3532 MODULE_PARM_DESC(forcecrt1,
3533 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
3534 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3535 "0=CRT1 OFF) (default: [autodetected])\n");
3537 MODULE_PARM_DESC(forcecrt2type,
3538 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3539 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3540 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3541 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3542 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3543 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3544 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3545 "depends on the very hardware in use. (default: [autodetected])\n");
3547 MODULE_PARM_DESC(scalelcd,
3548 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3549 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3550 "show black bars around the image, TMDS panels will probably do the scaling\n"
3551 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3553 MODULE_PARM_DESC(pdc,
3554 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3555 "should detect this correctly in most cases; however, sometimes this is not\n"
3556 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3557 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3558 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3559 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3561 MODULE_PARM_DESC(pdc1,
3562 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3563 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3564 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3565 "implemented yet.\n");
3567 MODULE_PARM_DESC(specialtiming,
3568 "\nPlease refer to documentation for more information on this option.\n");
3570 MODULE_PARM_DESC(lvdshl,
3571 "\nPlease refer to documentation for more information on this option.\n");
3573 MODULE_PARM_DESC(tvstandard,
3574 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3575 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3577 MODULE_PARM_DESC(tvxposoffset,
3578 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3581 MODULE_PARM_DESC(tvyposoffset,
3582 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3585 MODULE_PARM_DESC(filter,
3586 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3587 "(Possible values 0-7, default: [no filter])\n");
3589 MODULE_PARM_DESC(nocrt2rate,
3590 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3591 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3593 static int __init xgifb_init_module(void)
3595 printk("\nXGIfb_init_module");
3597 XGIfb_search_mode(mode);
3598 else if (vesa != -1)
3599 XGIfb_search_vesamode(vesa);
3601 return xgifb_init();
3604 static void __exit xgifb_remove_module(void)
3606 pci_unregister_driver(&xgifb_driver);
3607 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3610 module_init(xgifb_init_module);
3611 module_exit(xgifb_remove_module);
3613 #endif /* /MODULE */
3615 EXPORT_SYMBOL(XGI_malloc);
3616 EXPORT_SYMBOL(XGI_free);