2 * XG20, XG21, XG40, XG42 frame buffer device
3 * for Linux kernels 2.5.x, 2.6.x
4 * Base on TW's sis fbdev code.
7 /* #include <linux/config.h> */
8 #include <linux/version.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
20 #include <linux/console.h>
21 #include <linux/selection.h>
22 #include <linux/ioport.h>
23 #include <linux/init.h>
24 #include <linux/pci.h>
25 #include <linux/vmalloc.h>
26 #include <linux/vt_kern.h>
27 #include <linux/capability.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
48 #define Index_CR_GPIO_Reg1 0x48
49 #define Index_CR_GPIO_Reg2 0x49
50 #define Index_CR_GPIO_Reg3 0x4a
52 #define GPIOG_EN (1<<6)
53 #define GPIOG_WRITE (1<<6)
54 #define GPIOG_READ (1<<1)
55 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
57 #define XGIFB_ROM_SIZE 65536
59 /* -------------------- Macro definitions ---------------------------- */
64 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
66 #define DPRINTK(fmt, args...)
70 static void dumpVGAReg(void)
74 outXGIIDXREG(XGISR, 0x05, 0x86);
76 outXGIIDXREG(XGISR, 0x08, 0x4f);
77 outXGIIDXREG(XGISR, 0x0f, 0x20);
78 outXGIIDXREG(XGISR, 0x11, 0x4f);
79 outXGIIDXREG(XGISR, 0x13, 0x45);
80 outXGIIDXREG(XGISR, 0x14, 0x51);
81 outXGIIDXREG(XGISR, 0x1e, 0x41);
82 outXGIIDXREG(XGISR, 0x1f, 0x0);
83 outXGIIDXREG(XGISR, 0x20, 0xa1);
84 outXGIIDXREG(XGISR, 0x22, 0xfb);
85 outXGIIDXREG(XGISR, 0x26, 0x22);
86 outXGIIDXREG(XGISR, 0x3e, 0x07);
89 /* outXGIIDXREG(XGICR, 0x19, 0x00); */
90 /* outXGIIDXREG(XGICR, 0x1a, 0x3C); */
91 /* outXGIIDXREG(XGICR, 0x22, 0xff); */
92 /* outXGIIDXREG(XGICR, 0x3D, 0x10); */
94 /* outXGIIDXREG(XGICR, 0x4a, 0xf3); */
96 /* outXGIIDXREG(XGICR, 0x57, 0x0); */
97 /* outXGIIDXREG(XGICR, 0x7a, 0x2c); */
99 /* outXGIIDXREG(XGICR, 0x82, 0xcc); */
100 /* outXGIIDXREG(XGICR, 0x8c, 0x0); */
102 outXGIIDXREG(XGICR, 0x99, 0x1);
103 outXGIIDXREG(XGICR, 0x41, 0x40);
106 for (i = 0; i < 0x4f; i++) {
107 inXGIIDXREG(XGISR, i, reg);
108 printk("\no 3c4 %x", i);
109 printk("\ni 3c5 => %x", reg);
112 for (i = 0; i < 0xF0; i++) {
113 inXGIIDXREG(XGICR, i, reg);
114 printk("\no 3d4 %x", i);
115 printk("\ni 3d5 => %x", reg);
118 outXGIIDXREG(XGIPART1,0x2F,1);
119 for (i=1; i < 0x50; i++) {
120 inXGIIDXREG(XGIPART1, i, reg);
121 printk("\no d004 %x", i);
122 printk("\ni d005 => %x", reg);
125 for (i=0; i < 0x50; i++) {
126 inXGIIDXREG(XGIPART2, i, reg);
127 printk("\no d010 %x", i);
128 printk("\ni d011 => %x", reg);
130 for (i=0; i < 0x50; i++) {
131 inXGIIDXREG(XGIPART3, i, reg);
132 printk("\no d012 %x",i);
133 printk("\ni d013 => %x",reg);
135 for (i=0; i < 0x50; i++) {
136 inXGIIDXREG(XGIPART4, i, reg);
137 printk("\no d014 %x",i);
138 printk("\ni d015 => %x",reg);
143 static inline void dumpVGAReg(void)
148 /* data for XGI components */
149 struct video_info xgi_video_info;
154 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
157 /* --------------- Hardware Access Routines -------------------------- */
159 static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
160 struct xgi_hw_device_info *HwDeviceExtension,
161 unsigned char modeno, unsigned char rateindex)
163 unsigned short ModeNo = modeno;
164 unsigned short ModeIdIndex = 0, ClockIndex = 0;
165 unsigned short RefreshRateTableIndex = 0;
167 /* unsigned long temp = 0; */
169 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
170 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
172 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
173 ModeIdIndex, XGI_Pr);
176 temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
178 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
182 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
183 RefreshRateTableIndex += (rateindex - 1);
186 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
187 if (HwDeviceExtension->jChipType < XGI_315H)
190 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
195 static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
196 struct xgi_hw_device_info *HwDeviceExtension,
197 unsigned char modeno, unsigned char rateindex,
198 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
199 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
202 unsigned short ModeNo = modeno;
203 unsigned short ModeIdIndex = 0, index = 0;
204 unsigned short RefreshRateTableIndex = 0;
206 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
207 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
208 unsigned char sr_data, cr_data, cr_data2;
209 unsigned long cr_data3;
210 int A, B, C, D, E, F, temp, j;
211 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
212 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
213 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
214 ModeIdIndex, XGI_Pr);
216 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
220 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
221 RefreshRateTableIndex += (rateindex - 1);
223 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
225 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
227 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
229 /* Horizontal total */
230 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
234 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
236 Horizontal display enable end
237 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
239 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
242 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
244 /* Horizontal retrace (=sync) start */
245 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
248 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
250 /* Horizontal blank start */
251 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
253 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
255 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
257 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
259 /* Horizontal blank end */
260 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
261 | ((unsigned short) (sr_data & 0x03) << 6);
263 /* Horizontal retrace (=sync) end */
264 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
266 temp = HBE - ((E - 1) & 255);
267 B = (temp > 0) ? temp : (temp + 256);
269 temp = HRE - ((E + F + 3) & 63);
270 C = (temp > 0) ? temp : (temp + 64);
274 *left_margin = D * 8;
275 *right_margin = F * 8;
278 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
280 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
282 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
285 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
286 | ((unsigned short) (cr_data2 & 0x20) << 4)
287 | ((unsigned short) (sr_data & 0x01) << 10);
290 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
292 /* Vertical display enable end */
294 VDE = (cr_data & 0xff) |
295 ((unsigned short) (cr_data2 & 0x02) << 7) |
296 ((unsigned short) (cr_data2 & 0x40) << 3) |
297 ((unsigned short) (sr_data & 0x02) << 9);
299 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
302 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
304 /* Vertical retrace (=sync) start */
305 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
306 | ((unsigned short) (cr_data2 & 0x80) << 2)
307 | ((unsigned short) (sr_data & 0x08) << 7);
310 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
312 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
314 /* Vertical blank start */
315 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
316 | ((unsigned short) (cr_data3 & 0x20) << 4)
317 | ((unsigned short) (sr_data & 0x04) << 8);
319 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
321 /* Vertical blank end */
322 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
323 temp = VBE - ((E - 1) & 511);
324 B = (temp > 0) ? temp : (temp + 512);
326 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
328 /* Vertical retrace (=sync) end */
329 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
330 temp = VRE - ((E + F - 1) & 31);
331 C = (temp > 0) ? temp : (temp + 32);
339 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
340 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
342 *sync |= FB_SYNC_VERT_HIGH_ACT;
344 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
345 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
347 *sync |= FB_SYNC_HOR_HIGH_ACT;
349 *vmode = FB_VMODE_NONINTERLACED;
350 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
351 *vmode = FB_VMODE_INTERLACED;
354 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
355 if (XGI_Pr->EModeIDTable[j].Ext_ModeID
356 == XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
357 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag
359 *vmode = FB_VMODE_DOUBLE;
370 static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
372 XGI_Pr->RelIO = BaseAddr;
373 XGI_Pr->P3c4 = BaseAddr + 0x14;
374 XGI_Pr->P3d4 = BaseAddr + 0x24;
375 XGI_Pr->P3c0 = BaseAddr + 0x10;
376 XGI_Pr->P3ce = BaseAddr + 0x1e;
377 XGI_Pr->P3c2 = BaseAddr + 0x12;
378 XGI_Pr->P3ca = BaseAddr + 0x1a;
379 XGI_Pr->P3c6 = BaseAddr + 0x16;
380 XGI_Pr->P3c7 = BaseAddr + 0x17;
381 XGI_Pr->P3c8 = BaseAddr + 0x18;
382 XGI_Pr->P3c9 = BaseAddr + 0x19;
383 XGI_Pr->P3da = BaseAddr + 0x2A;
384 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
385 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
386 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
387 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
388 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2; /* 301 palette address port registers */
392 void XGIfb_set_reg4(u16 port, unsigned long data)
394 outl((u32)(data & 0xffffffff), port);
397 u32 XGIfb_get_reg3(u16 port)
405 /* ------------ Interface for init & mode switching code ------------- */
407 unsigned char XGIfb_query_VGA_config_space(
408 struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
409 unsigned long set, unsigned long *value)
411 static struct pci_dev *pdev = NULL;
412 static unsigned char init = 0, valid_pdev = 0;
415 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
417 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
421 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
430 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
431 xgi_video_info.chip_id);
436 pci_read_config_dword(pdev, offset, (u32 *) value);
438 pci_write_config_dword(pdev, offset, (u32)(*value));
444 unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
445 unsigned long offset, unsigned long set, unsigned long *value)
447 static struct pci_dev *pdev = NULL;
448 static unsigned char init = 0, valid_pdev = 0;
453 switch (xgi_video_info.chip) {
455 nbridge_id = PCI_DEVICE_ID_XG_540;
458 nbridge_id = PCI_DEVICE_ID_XG_630;
461 nbridge_id = PCI_DEVICE_ID_XG_730;
464 nbridge_id = PCI_DEVICE_ID_XG_550;
467 nbridge_id = PCI_DEVICE_ID_XG_650;
470 nbridge_id = PCI_DEVICE_ID_XG_740;
477 pdev = pci_get_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
485 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
491 pci_read_config_dword(pdev, offset, (u32 *)value);
493 pci_write_config_dword(pdev, offset, (u32)(*value));
498 /* ------------------ Internal helper routines ----------------- */
500 static void XGIfb_search_mode(const char *name)
505 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
506 xgifb_mode_idx = DEFAULT_MODE;
507 if ((xgi_video_info.chip == XG21)
508 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
510 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
515 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
516 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
517 xgifb_mode_idx = DEFAULT_MODE;
518 if ((xgi_video_info.chip == XG21)
519 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
521 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
526 while (XGIbios_mode[i].mode_no != 0) {
527 l = min(strlen(name), strlen(XGIbios_mode[i].name));
528 if (!strncmp(name, XGIbios_mode[i].name, l)) {
536 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
539 static void XGIfb_search_vesamode(unsigned int vesamode)
545 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
546 xgifb_mode_idx = DEFAULT_MODE;
547 if ((xgi_video_info.chip == XG21)
548 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
550 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
555 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
557 while (XGIbios_mode[i].mode_no != 0) {
558 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode)
559 || (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
567 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
570 static int XGIfb_GetXG21LVDSData(void)
573 unsigned char *pData;
576 inXGIIDXREG(XGISR, 0x1e, tmp);
577 outXGIIDXREG(XGISR, 0x1e, tmp | 4);
579 pData = xgi_video_info.mmio_vbase + 0x20000;
580 if ((pData[0x0] == 0x55) && (pData[0x1] == 0xAA) && (pData[0x65] & 0x1)) {
581 i = pData[0x316] | (pData[0x317] << 8);
588 XGI21_LCDCapList[k].LVDS_Capability = pData[i]
589 | (pData[i + 1] << 8);
590 XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
592 XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
594 XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
596 XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
598 XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
600 XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
602 XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
603 | (pData[i + 15] << 8);
604 XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
605 | (pData[i + 17] << 8);
606 XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
607 XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
608 XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
609 XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
610 XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
611 XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
612 XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
616 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
617 / sizeof(struct XGI21_LVDSCapStruct))));
623 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
627 int XGIfb_mode_idx = 0;
630 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
631 && (XGIbios_mode[XGIfb_mode_idx].xres
632 <= XGI21_LCDCapList[0].LVDSHDE)) {
633 if ((XGIbios_mode[XGIfb_mode_idx].xres
634 == XGI21_LCDCapList[0].LVDSHDE)
635 && (XGIbios_mode[XGIfb_mode_idx].yres
636 == XGI21_LCDCapList[0].LVDSVDE)
637 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
638 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
647 return XGIfb_mode_idx;
650 static int XGIfb_validate_mode(int myindex)
654 if (xgi_video_info.chip == XG21) {
655 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
657 xres = XGI21_LCDCapList[0].LVDSHDE;
658 yres = XGI21_LCDCapList[0].LVDSVDE;
659 if (XGIbios_mode[myindex].xres > xres)
661 if (XGIbios_mode[myindex].yres > yres)
663 if ((XGIbios_mode[myindex].xres < xres)
664 && (XGIbios_mode[myindex].yres < yres)) {
665 if (XGIbios_mode[myindex].bpp > 8)
674 /* FIXME: for now, all is valid on XG27 */
675 if (xgi_video_info.chip == XG27)
678 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
681 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
683 switch (XGIhw_ext.ulCRT2LCDType) {
724 /* case LCD_320x480: */ /* TW: FSTN */
735 if (XGIbios_mode[myindex].xres > xres)
737 if (XGIbios_mode[myindex].yres > yres)
739 if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
740 (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
741 switch (XGIbios_mode[myindex].xres) {
743 if (XGIbios_mode[myindex].yres != 512)
745 if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
749 if ((XGIbios_mode[myindex].yres != 400)
750 && (XGIbios_mode[myindex].yres
755 if (XGIbios_mode[myindex].yres != 600)
759 if ((XGIbios_mode[myindex].yres != 600)
760 && (XGIbios_mode[myindex].yres
763 if ((XGIbios_mode[myindex].yres == 600)
764 && (XGIhw_ext.ulCRT2LCDType
769 if ((XGIbios_mode[myindex].yres) != 768)
771 if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
775 if ((XGIbios_mode[myindex].yres != 768)
776 && (XGIbios_mode[myindex].yres
779 if ((XGIbios_mode[myindex].yres == 768)
780 && (XGIhw_ext.ulCRT2LCDType
785 if (XGIbios_mode[myindex].yres != 1050)
789 if (XGIbios_mode[myindex].yres != 1200)
796 switch (XGIbios_mode[myindex].xres) {
798 if (XGIbios_mode[myindex].yres != 512)
802 if ((XGIbios_mode[myindex].yres != 400)
803 && (XGIbios_mode[myindex].yres
808 if (XGIbios_mode[myindex].yres != 600)
812 if (XGIbios_mode[myindex].yres != 768)
816 if ((XGIbios_mode[myindex].yres != 960)
817 && (XGIbios_mode[myindex].yres
820 if (XGIbios_mode[myindex].yres == 960) {
821 if (XGIhw_ext.ulCRT2LCDType
827 if (XGIbios_mode[myindex].yres != 1050)
831 if (XGIbios_mode[myindex].yres != 1200)
840 switch (XGIbios_mode[myindex].xres) {
846 if (xgi_video_info.TV_type == TVMODE_NTSC) {
847 if (XGIbios_mode[myindex].yres != 480)
849 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
850 if (XGIbios_mode[myindex].yres != 576)
853 /* TW: LVDS/CHRONTEL does not support 720 */
854 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
855 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
860 if (xgi_video_info.TV_type == TVMODE_NTSC) {
861 if (XGIbios_mode[myindex].bpp == 32)
864 /* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) */
865 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
866 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
867 if (xgi_video_info.chip < XGI_315H)
876 if (XGIbios_mode[myindex].xres > 1280)
884 static void XGIfb_search_crt2type(const char *name)
891 while (XGI_crt2type[i].type_no != -1) {
892 if (!strcmp(name, XGI_crt2type[i].name)) {
893 XGIfb_crt2type = XGI_crt2type[i].type_no;
894 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
899 if (XGIfb_crt2type < 0)
900 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
903 static void XGIfb_search_queuemode(const char *name)
910 while (XGI_queuemode[i].type_no != -1) {
911 if (!strcmp(name, XGI_queuemode[i].name)) {
912 XGIfb_queuemode = XGI_queuemode[i].type_no;
917 if (XGIfb_queuemode < 0)
918 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
921 static u8 XGIfb_search_refresh_rate(unsigned int rate)
926 xres = XGIbios_mode[xgifb_mode_idx].xres;
927 yres = XGIbios_mode[xgifb_mode_idx].yres;
930 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
931 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres
933 if (XGIfb_vrate[i].refresh == rate) {
934 XGIfb_rate_idx = XGIfb_vrate[i].idx;
936 } else if (XGIfb_vrate[i].refresh > rate) {
937 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
938 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
939 rate, XGIfb_vrate[i].refresh);
940 XGIfb_rate_idx = XGIfb_vrate[i].idx;
941 xgi_video_info.refresh_rate
942 = XGIfb_vrate[i].refresh;
943 } else if (((rate - XGIfb_vrate[i - 1].refresh)
944 <= 2) && (XGIfb_vrate[i].idx
946 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
947 rate, XGIfb_vrate[i-1].refresh);
948 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
949 xgi_video_info.refresh_rate
950 = XGIfb_vrate[i - 1].refresh;
953 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
954 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
955 rate, XGIfb_vrate[i].refresh);
956 XGIfb_rate_idx = XGIfb_vrate[i].idx;
962 if (XGIfb_rate_idx > 0) {
963 return XGIfb_rate_idx;
966 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
971 static void XGIfb_search_tvstd(const char *name)
978 while (XGI_tvtype[i].type_no != -1) {
979 if (!strcmp(name, XGI_tvtype[i].name)) {
980 XGIfb_tvmode = XGI_tvtype[i].type_no;
987 static unsigned char XGIfb_bridgeisslave(void)
989 unsigned char usScratchP1_00;
991 if (xgi_video_info.hasVB == HASVB_NONE)
994 inXGIIDXREG(XGIPART1, 0x00, usScratchP1_00);
995 if ((usScratchP1_00 & 0x50) == 0x10)
1001 static unsigned char XGIfbcheckvretracecrt1(void)
1005 inXGIIDXREG(XGICR, 0x17, temp);
1009 inXGIIDXREG(XGISR, 0x1f, temp);
1013 if (inXGIREG(XGIINPSTAT) & 0x08)
1019 static unsigned char XGIfbcheckvretracecrt2(void)
1022 if (xgi_video_info.hasVB == HASVB_NONE)
1024 inXGIIDXREG(XGIPART1, 0x30, temp);
1031 static unsigned char XGIfb_CheckVBRetrace(void)
1033 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1034 if (XGIfb_bridgeisslave())
1035 return XGIfbcheckvretracecrt1();
1037 return XGIfbcheckvretracecrt2();
1039 return XGIfbcheckvretracecrt1();
1042 /* ----------- FBDev related routines for all series ----------- */
1044 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1046 switch (var->bits_per_pixel) {
1048 var->red.offset = var->green.offset = var->blue.offset = 0;
1049 var->red.length = var->green.length = var->blue.length = 6;
1050 xgi_video_info.video_cmap_len = 256;
1053 var->red.offset = 11;
1054 var->red.length = 5;
1055 var->green.offset = 5;
1056 var->green.length = 6;
1057 var->blue.offset = 0;
1058 var->blue.length = 5;
1059 var->transp.offset = 0;
1060 var->transp.length = 0;
1061 xgi_video_info.video_cmap_len = 16;
1064 var->red.offset = 16;
1065 var->red.length = 8;
1066 var->green.offset = 8;
1067 var->green.length = 8;
1068 var->blue.offset = 0;
1069 var->blue.length = 8;
1070 var->transp.offset = 24;
1071 var->transp.length = 8;
1072 xgi_video_info.video_cmap_len = 16;
1077 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1078 struct fb_info *info)
1081 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1083 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1085 #if defined(__powerpc__)
1086 u8 sr_data, cr_data;
1088 unsigned int drate = 0, hrate = 0;
1091 /* unsigned char reg, reg1; */
1093 DEBUGPRN("Inside do_set_var");
1094 /* 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); */
1096 info->var.xres_virtual = var->xres_virtual;
1097 info->var.yres_virtual = var->yres_virtual;
1098 info->var.bits_per_pixel = var->bits_per_pixel;
1100 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1102 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1104 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1106 /* var->yres <<= 1; */
1109 if (!htotal || !vtotal) {
1110 DPRINTK("XGIfb: Invalid 'var' information\n");
1112 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1113 var->pixclock, htotal, vtotal);
1115 if (var->pixclock && htotal && vtotal) {
1116 drate = 1000000000 / var->pixclock;
1117 hrate = (drate * 1000) / htotal;
1118 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1121 xgi_video_info.refresh_rate = 60;
1124 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1125 var->xres, var->yres, var->bits_per_pixel, xgi_video_info.refresh_rate);
1127 old_mode = xgifb_mode_idx;
1130 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1131 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1132 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1133 && (XGIbios_mode[xgifb_mode_idx].yres
1135 && (XGIbios_mode[xgifb_mode_idx].bpp
1136 == var->bits_per_pixel)) {
1137 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1145 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1147 xgifb_mode_idx = -1;
1149 if (xgifb_mode_idx < 0) {
1150 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1151 var->yres, var->bits_per_pixel);
1152 xgifb_mode_idx = old_mode;
1156 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1157 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1158 xgi_video_info.refresh_rate = 60;
1163 XGIfb_pre_setmode();
1164 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1165 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1168 info->fix.line_length = ((info->var.xres_virtual
1169 * info->var.bits_per_pixel) >> 6);
1171 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1173 outXGIIDXREG(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1174 outXGIIDXREG(XGISR, 0x0E, (info->fix.line_length & 0xff00) >> 8);
1176 XGIfb_post_setmode();
1178 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1179 XGIbios_mode[xgifb_mode_idx].xres,
1180 XGIbios_mode[xgifb_mode_idx].yres,
1181 XGIbios_mode[xgifb_mode_idx].bpp,
1182 xgi_video_info.refresh_rate);
1184 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1185 xgi_video_info.video_vwidth = info->var.xres_virtual;
1186 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1187 xgi_video_info.video_vheight = info->var.yres_virtual;
1188 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1189 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1190 xgi_video_info.video_linelength = info->var.xres_virtual
1191 * (xgi_video_info.video_bpp >> 3);
1192 xgi_video_info.accel = 0;
1194 xgi_video_info.accel = (var->accel_flags
1195 & FB_ACCELF_TEXT) ? -1 : 0;
1197 switch (xgi_video_info.video_bpp) {
1199 xgi_video_info.DstColor = 0x0000;
1200 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1201 xgi_video_info.video_cmap_len = 256;
1202 #if defined(__powerpc__)
1203 inXGIIDXREG(XGICR, 0x4D, cr_data);
1204 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1208 xgi_video_info.DstColor = 0x8000;
1209 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1210 #if defined(__powerpc__)
1211 inXGIIDXREG(XGICR, 0x4D, cr_data);
1212 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1214 xgi_video_info.video_cmap_len = 16;
1217 xgi_video_info.DstColor = 0xC000;
1218 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1219 xgi_video_info.video_cmap_len = 16;
1220 #if defined(__powerpc__)
1221 inXGIIDXREG(XGICR, 0x4D, cr_data);
1222 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1226 xgi_video_info.video_cmap_len = 16;
1227 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1228 xgi_video_info.accel = 0;
1232 XGIfb_bpp_to_var(var); /*update ARGB info*/
1233 DEBUGPRN("End of do_set_var");
1240 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1244 /* printk("Inside pan_var"); */
1246 if (var->xoffset > (var->xres_virtual - var->xres)) {
1247 /* printk("Pan: xo: %d xv %d xr %d\n",
1248 var->xoffset, var->xres_virtual, var->xres); */
1251 if (var->yoffset > (var->yres_virtual - var->yres)) {
1252 /* printk("Pan: yo: %d yv %d yr %d\n",
1253 var->yoffset, var->yres_virtual, var->yres); */
1256 base = var->yoffset * var->xres_virtual + var->xoffset;
1258 /* calculate base bpp dep. */
1259 switch (var->bits_per_pixel) {
1271 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1273 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1274 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1275 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1276 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1277 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1279 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1280 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1281 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1282 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1283 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1284 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1286 /* printk("End of pan_var"); */
1291 void XGI_dispinfo(struct ap_data *rec)
1293 rec->minfo.bpp = xgi_video_info.video_bpp;
1294 rec->minfo.xres = xgi_video_info.video_width;
1295 rec->minfo.yres = xgi_video_info.video_height;
1296 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1297 rec->minfo.v_yres = xgi_video_info.video_vheight;
1298 rec->minfo.org_x = xgi_video_info.org_x;
1299 rec->minfo.org_y = xgi_video_info.org_y;
1300 rec->minfo.vrate = xgi_video_info.refresh_rate;
1301 rec->iobase = xgi_video_info.vga_base - 0x30;
1302 rec->mem_size = xgi_video_info.video_size;
1303 rec->disp_state = xgi_video_info.disp_state;
1304 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1305 rec->hasVB = xgi_video_info.hasVB;
1306 rec->TV_type = xgi_video_info.TV_type;
1307 rec->TV_plug = xgi_video_info.TV_plug;
1308 rec->chip = xgi_video_info.chip;
1311 static int XGIfb_open(struct fb_info *info, int user)
1316 static int XGIfb_release(struct fb_info *info, int user)
1321 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1325 switch (var->bits_per_pixel) {
1339 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1340 unsigned blue, unsigned transp, struct fb_info *info)
1342 if (regno >= XGIfb_get_cmap_len(&info->var))
1345 switch (info->var.bits_per_pixel) {
1347 outXGIREG(XGIDACA, regno);
1348 outXGIREG(XGIDACD, (red >> 10));
1349 outXGIREG(XGIDACD, (green >> 10));
1350 outXGIREG(XGIDACD, (blue >> 10));
1351 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1352 outXGIREG(XGIDAC2A, regno);
1353 outXGIREG(XGIDAC2D, (red >> 8));
1354 outXGIREG(XGIDAC2D, (green >> 8));
1355 outXGIREG(XGIDAC2D, (blue >> 8));
1359 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1360 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1367 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1374 static int XGIfb_set_par(struct fb_info *info)
1378 /* printk("XGIfb: inside set_par\n"); */
1379 err = XGIfb_do_set_var(&info->var, 1, info);
1382 XGIfb_get_fix(&info->fix, -1, info);
1383 /* printk("XGIfb: end of set_par\n"); */
1387 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1389 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1391 unsigned int vtotal = 0;
1392 unsigned int drate = 0, hrate = 0;
1394 int refresh_rate, search_idx;
1396 DEBUGPRN("Inside check_var");
1398 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1399 vtotal = var->upper_margin + var->yres + var->lower_margin
1402 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1403 vtotal = var->upper_margin + var->yres + var->lower_margin
1406 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1407 vtotal = var->upper_margin + (var->yres / 2)
1408 + var->lower_margin + var->vsync_len;
1410 vtotal = var->upper_margin + var->yres + var->lower_margin
1413 if (!(htotal) || !(vtotal))
1414 XGIFAIL("XGIfb: no valid timing data");
1416 if (var->pixclock && htotal && vtotal) {
1417 drate = 1000000000 / var->pixclock;
1418 hrate = (drate * 1000) / htotal;
1419 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1421 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1422 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1423 __func__, var->pixclock, htotal, vtotal,
1424 __func__, drate, hrate, xgi_video_info.refresh_rate);
1426 xgi_video_info.refresh_rate = 60;
1430 if ((var->pixclock) && (htotal)) {
1431 drate = 1E12 / var->pixclock;
1432 hrate = drate / htotal;
1433 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1438 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1439 if ((var->xres == 1024) && (var->yres == 600))
1443 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1444 (XGIbios_mode[search_idx].xres <= var->xres)) {
1445 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1446 (XGIbios_mode[search_idx].yres == var->yres) &&
1447 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1448 if (XGIfb_validate_mode(search_idx) > 0) {
1458 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1459 var->xres, var->yres, var->bits_per_pixel);
1461 while (XGIbios_mode[search_idx].mode_no != 0) {
1463 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1464 (var->yres <= XGIbios_mode[search_idx].yres) &&
1465 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1466 if (XGIfb_validate_mode(search_idx) > 0) {
1474 var->xres = XGIbios_mode[search_idx].xres;
1475 var->yres = XGIbios_mode[search_idx].yres;
1476 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1477 var->xres, var->yres, var->bits_per_pixel);
1480 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1481 var->xres, var->yres, var->bits_per_pixel);
1486 /* TW: TODO: Check the refresh rate */
1488 /* Adapt RGB settings */
1489 XGIfb_bpp_to_var(var);
1491 /* Sanity check for offsets */
1492 if (var->xoffset < 0)
1494 if (var->yoffset < 0)
1498 if (var->xres != var->xres_virtual)
1499 var->xres_virtual = var->xres;
1500 if (var->yres != var->yres_virtual)
1501 var->yres_virtual = var->yres;
1503 /* TW: Now patch yres_virtual if we use panning */
1504 /* May I do this? */
1505 /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1506 /* if (var->yres_virtual <= var->yres) { */
1507 /* TW: Paranoia check */
1508 /* var->yres_virtual = var->yres; */
1512 /* Truncate offsets to maximum if too high */
1513 if (var->xoffset > var->xres_virtual - var->xres)
1514 var->xoffset = var->xres_virtual - var->xres - 1;
1516 if (var->yoffset > var->yres_virtual - var->yres)
1517 var->yoffset = var->yres_virtual - var->yres - 1;
1519 /* Set everything else to 0 */
1520 var->red.msb_right =
1521 var->green.msb_right =
1522 var->blue.msb_right =
1523 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1525 DEBUGPRN("end of check_var");
1530 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1531 struct fb_info *info)
1535 /* printk("\nInside pan_display:\n"); */
1537 if (var->xoffset > (var->xres_virtual - var->xres))
1539 if (var->yoffset > (var->yres_virtual - var->yres))
1542 if (var->vmode & FB_VMODE_YWRAP) {
1543 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1547 if (var->xoffset + info->var.xres > info->var.xres_virtual
1548 || var->yoffset + info->var.yres
1549 > info->var.yres_virtual)
1552 err = XGIfb_pan_var(var);
1556 info->var.xoffset = var->xoffset;
1557 info->var.yoffset = var->yoffset;
1558 if (var->vmode & FB_VMODE_YWRAP)
1559 info->var.vmode |= FB_VMODE_YWRAP;
1561 info->var.vmode &= ~FB_VMODE_YWRAP;
1563 /* printk("End of pan_display\n"); */
1568 static int XGIfb_blank(int blank, struct fb_info *info)
1572 inXGIIDXREG(XGICR, 0x17, reg);
1579 outXGIIDXREG(XGICR, 0x17, reg);
1580 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1581 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1585 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1588 DEBUGPRN("inside ioctl");
1591 if (!capable(CAP_SYS_RAWIO))
1593 XGI_malloc((struct XGI_memreq *) arg);
1596 if (!capable(CAP_SYS_RAWIO))
1598 XGI_free(*(unsigned long *) arg);
1600 case FBIOGET_HWCINFO: {
1601 unsigned long *hwc_offset = (unsigned long *) arg;
1603 if (XGIfb_caps & HW_CURSOR_CAP)
1605 = XGIfb_hwcursor_vbase
1606 - (unsigned long) xgi_video_info.video_vbase;
1612 case FBIOPUT_MODEINFO: {
1613 struct mode_info *x = (struct mode_info *) arg;
1615 xgi_video_info.video_bpp = x->bpp;
1616 xgi_video_info.video_width = x->xres;
1617 xgi_video_info.video_height = x->yres;
1618 xgi_video_info.video_vwidth = x->v_xres;
1619 xgi_video_info.video_vheight = x->v_yres;
1620 xgi_video_info.org_x = x->org_x;
1621 xgi_video_info.org_y = x->org_y;
1622 xgi_video_info.refresh_rate = x->vrate;
1623 xgi_video_info.video_linelength = xgi_video_info.video_vwidth
1624 * (xgi_video_info.video_bpp >> 3);
1625 switch (xgi_video_info.video_bpp) {
1627 xgi_video_info.DstColor = 0x0000;
1628 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1629 xgi_video_info.video_cmap_len = 256;
1632 xgi_video_info.DstColor = 0x8000;
1633 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1634 xgi_video_info.video_cmap_len = 16;
1637 xgi_video_info.DstColor = 0xC000;
1638 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1639 xgi_video_info.video_cmap_len = 16;
1642 xgi_video_info.video_cmap_len = 16;
1643 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1644 xgi_video_info.accel = 0;
1650 case FBIOGET_DISPINFO:
1651 XGI_dispinfo((struct ap_data *) arg);
1653 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1655 struct XGIfb_info *x = (struct XGIfb_info *) arg;
1657 /* x->XGIfb_id = XGIFB_ID; */
1658 x->XGIfb_version = VER_MAJOR;
1659 x->XGIfb_revision = VER_MINOR;
1660 x->XGIfb_patchlevel = VER_LEVEL;
1661 x->chip_id = xgi_video_info.chip_id;
1662 x->memory = xgi_video_info.video_size / 1024;
1663 x->heapstart = xgi_video_info.heapstart / 1024;
1664 x->fbvidmode = XGIfb_mode_no;
1665 x->XGIfb_caps = XGIfb_caps;
1666 x->XGIfb_tqlen = 512; /* yet unused */
1667 x->XGIfb_pcibus = xgi_video_info.pcibus;
1668 x->XGIfb_pcislot = xgi_video_info.pcislot;
1669 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1670 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1671 x->XGIfb_lcda = XGIfb_detectedlcda;
1674 case XGIFB_GET_VBRSTATUS: {
1675 unsigned long *vbrstatus = (unsigned long *) arg;
1676 if (XGIfb_CheckVBRetrace())
1683 } DEBUGPRN("end of ioctl");
1688 /* ----------- FBDev related routines for all series ---------- */
1690 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1691 struct fb_info *info)
1693 DEBUGPRN("inside get_fix");
1694 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1696 strcpy(fix->id, myid);
1698 fix->smem_start = xgi_video_info.video_base;
1700 fix->smem_len = xgi_video_info.video_size;
1702 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1703 if (xgi_video_info.video_size > 0x1000000) {
1704 fix->smem_len = 0xD00000;
1705 } else if (xgi_video_info.video_size > 0x800000)
1706 fix->smem_len = 0x800000;
1708 fix->smem_len = 0x400000;
1710 fix->smem_len = XGIfb_mem * 1024;
1712 fix->type = video_type;
1714 if (xgi_video_info.video_bpp == 8)
1715 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1717 fix->visual = FB_VISUAL_DIRECTCOLOR;
1724 fix->line_length = xgi_video_info.video_linelength;
1725 fix->mmio_start = xgi_video_info.mmio_base;
1726 fix->mmio_len = xgi_video_info.mmio_size;
1727 if (xgi_video_info.chip >= XG40)
1728 fix->accel = FB_ACCEL_XGI_XABRE;
1730 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1732 DEBUGPRN("end of get_fix");
1736 static struct fb_ops XGIfb_ops = {
1737 .owner = THIS_MODULE,
1738 .fb_open = XGIfb_open,
1739 .fb_release = XGIfb_release,
1740 .fb_check_var = XGIfb_check_var,
1741 .fb_set_par = XGIfb_set_par,
1742 .fb_setcolreg = XGIfb_setcolreg,
1744 .fb_pan_display = XGIfb_pan_display,
1746 .fb_blank = XGIfb_blank,
1747 .fb_fillrect = fbcon_XGI_fillrect,
1748 .fb_copyarea = fbcon_XGI_copyarea,
1749 .fb_imageblit = cfb_imageblit,
1750 .fb_sync = fbcon_XGI_sync,
1751 .fb_ioctl = XGIfb_ioctl,
1752 /* .fb_mmap = XGIfb_mmap, */
1755 /* ---------------- Chip generation dependent routines ---------------- */
1757 /* for XGI 315/550/650/740/330 */
1759 static int XGIfb_get_dram_size(void)
1765 /* xorg driver sets 32MB * 1 channel */
1766 if (xgi_video_info.chip == XG27)
1767 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1769 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1770 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1771 case XGI_DRAM_SIZE_1MB:
1772 xgi_video_info.video_size = 0x100000;
1774 case XGI_DRAM_SIZE_2MB:
1775 xgi_video_info.video_size = 0x200000;
1777 case XGI_DRAM_SIZE_4MB:
1778 xgi_video_info.video_size = 0x400000;
1780 case XGI_DRAM_SIZE_8MB:
1781 xgi_video_info.video_size = 0x800000;
1783 case XGI_DRAM_SIZE_16MB:
1784 xgi_video_info.video_size = 0x1000000;
1786 case XGI_DRAM_SIZE_32MB:
1787 xgi_video_info.video_size = 0x2000000;
1789 case XGI_DRAM_SIZE_64MB:
1790 xgi_video_info.video_size = 0x4000000;
1792 case XGI_DRAM_SIZE_128MB:
1793 xgi_video_info.video_size = 0x8000000;
1795 case XGI_DRAM_SIZE_256MB:
1796 xgi_video_info.video_size = 0x10000000;
1802 tmp = (reg & 0x0c) >> 2;
1803 switch (xgi_video_info.chip) {
1839 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1840 /* PLiad fixed for benchmarking and fb set */
1841 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1842 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1844 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1845 xgi_video_info.video_size, ChannelNum);
1850 static void XGIfb_detect_VB(void)
1854 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1856 switch (xgi_video_info.hasVB) {
1857 case HASVB_LVDS_CHRONTEL:
1858 case HASVB_CHRONTEL:
1862 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1866 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1868 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1877 if (XGIfb_crt2type != -1)
1878 /* TW: Override with option */
1879 xgi_video_info.disp_state = XGIfb_crt2type;
1880 else if (cr32 & XGI_VB_TV)
1881 xgi_video_info.disp_state = DISPTYPE_TV;
1882 else if (cr32 & XGI_VB_LCD)
1883 xgi_video_info.disp_state = DISPTYPE_LCD;
1884 else if (cr32 & XGI_VB_CRT2)
1885 xgi_video_info.disp_state = DISPTYPE_CRT2;
1887 xgi_video_info.disp_state = 0;
1889 if (XGIfb_tvplug != -1)
1890 /* PR/TW: Override with option */
1891 xgi_video_info.TV_plug = XGIfb_tvplug;
1892 else if (cr32 & XGI_VB_HIVISION) {
1893 xgi_video_info.TV_type = TVMODE_HIVISION;
1894 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1895 } else if (cr32 & XGI_VB_SVIDEO)
1896 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1897 else if (cr32 & XGI_VB_COMPOSITE)
1898 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1899 else if (cr32 & XGI_VB_SCART)
1900 xgi_video_info.TV_plug = TVPLUG_SCART;
1902 if (xgi_video_info.TV_type == 0) {
1903 /* TW: PAL/NTSC changed for 650 */
1904 if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
1907 inXGIIDXREG(XGICR, 0x38, temp);
1909 xgi_video_info.TV_type = TVMODE_PAL;
1911 xgi_video_info.TV_type = TVMODE_NTSC;
1915 inXGIIDXREG(XGICR, 0x79, temp);
1917 xgi_video_info.TV_type = TVMODE_PAL;
1919 xgi_video_info.TV_type = TVMODE_NTSC;
1923 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1924 if (XGIfb_forcecrt1 != -1) {
1925 if (XGIfb_forcecrt1)
1932 static void XGIfb_get_VB_type(void)
1936 if (!XGIfb_has_VB()) {
1937 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1938 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1939 case XGI310_EXTERNAL_CHIP_LVDS:
1940 xgi_video_info.hasVB = HASVB_LVDS;
1942 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1943 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1951 static int XGIfb_has_VB(void)
1955 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1956 switch (vb_chipid) {
1958 xgi_video_info.hasVB = HASVB_301;
1961 xgi_video_info.hasVB = HASVB_302;
1964 xgi_video_info.hasVB = HASVB_NONE;
1970 /* ------------------ Sensing routines ------------------ */
1972 /* TW: Determine and detect attached devices on XGI30x */
1973 int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1977 outXGIIDXREG(XGIPART4, 0x11, tempbl);
1978 temp = tempbh | tempcl;
1979 setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1980 for (i = 0; i < 10; i++)
1981 XGI_LongWait(&XGI_Pr);
1983 inXGIIDXREG(XGIPART4, 0x03, temp);
1989 void XGI_Sense30x(void)
1992 u8 testsvhs_tempbl, testsvhs_tempbh;
1993 u8 testsvhs_tempcl, testsvhs_tempch;
1994 u8 testcvbs_tempbl, testcvbs_tempbh;
1995 u8 testcvbs_tempcl, testcvbs_tempch;
1996 u8 testvga2_tempbl, testvga2_tempbh;
1997 u8 testvga2_tempcl, testvga2_tempch;
2000 inXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
2001 outXGIIDXREG(XGIPART4, 0x0d, (backupP4_0d | 0x04));
2003 testvga2_tempbh = 0x00;
2004 testvga2_tempbl = 0xd1;
2005 testsvhs_tempbh = 0x00;
2006 testsvhs_tempbl = 0xb9;
2007 testcvbs_tempbh = 0x00;
2008 testcvbs_tempbl = 0xb3;
2009 if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
2011 testvga2_tempbh = 0x01;
2012 testvga2_tempbl = 0x90;
2013 testsvhs_tempbh = 0x01;
2014 testsvhs_tempbl = 0x6b;
2015 testcvbs_tempbh = 0x01;
2016 testcvbs_tempbl = 0x74;
2017 if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
2018 || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2019 testvga2_tempbh = 0x00;
2020 testvga2_tempbl = 0x00;
2021 testsvhs_tempbh = 0x02;
2022 testsvhs_tempbl = 0x00;
2023 testcvbs_tempbh = 0x01;
2024 testcvbs_tempbl = 0x00;
2027 if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
2029 inXGIIDXREG(XGIPART4, 0x01, myflag);
2030 if (myflag & 0x04) {
2031 testvga2_tempbh = 0x00;
2032 testvga2_tempbl = 0xfd;
2033 testsvhs_tempbh = 0x00;
2034 testsvhs_tempbl = 0xdd;
2035 testcvbs_tempbh = 0x00;
2036 testcvbs_tempbl = 0xee;
2039 if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
2040 == VB_CHIP_302LV)) {
2041 testvga2_tempbh = 0x00;
2042 testvga2_tempbl = 0x00;
2043 testvga2_tempch = 0x00;
2044 testvga2_tempcl = 0x00;
2045 testsvhs_tempch = 0x04;
2046 testsvhs_tempcl = 0x08;
2047 testcvbs_tempch = 0x08;
2048 testcvbs_tempcl = 0x08;
2050 testvga2_tempch = 0x0e;
2051 testvga2_tempcl = 0x08;
2052 testsvhs_tempch = 0x06;
2053 testsvhs_tempcl = 0x04;
2054 testcvbs_tempch = 0x08;
2055 testcvbs_tempcl = 0x04;
2058 if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
2059 || testvga2_tempbl) {
2060 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2061 testvga2_tempcl, testvga2_tempch);
2063 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2064 orXGIIDXREG(XGICR, 0x32, 0x10);
2068 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
2071 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2072 /* TW: So we can be sure that there IS a SVHS output */
2073 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2074 orXGIIDXREG(XGICR, 0x32, 0x02);
2078 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2079 testcvbs_tempcl, testcvbs_tempch);
2081 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2082 /* TW: So we can be sure that there IS a CVBS output */
2083 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2084 orXGIIDXREG(XGICR, 0x32, 0x01);
2087 XGIDoSense(0, 0, 0, 0);
2089 outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
2092 /* ------------------------ Heap routines -------------------------- */
2094 static int XGIfb_heap_init(void)
2099 int agp_enabled = 1;
2101 unsigned long *cmdq_baseport = NULL;
2102 unsigned long *read_port = NULL;
2103 unsigned long *write_port = NULL;
2104 XGI_CMDTYPE cmd_type;
2106 struct agp_kern_info *agp_info;
2107 struct agp_memory *agp;
2111 /* TW: The heap start is either set manually using the "mem" parameter, or
2112 * defaults as follows:
2113 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2114 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2115 * -) If 4MB or less is available, let it start at 4MB.
2116 * This is for avoiding a clash with X driver which uses the beginning
2117 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2119 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2120 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2122 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
2123 if (xgi_video_info.video_size > 0x1000000)
2124 xgi_video_info.heapstart = 0xD00000;
2125 else if (xgi_video_info.video_size > 0x800000)
2126 xgi_video_info.heapstart = 0x800000;
2128 xgi_video_info.heapstart = 0x400000;
2130 xgi_video_info.heapstart = XGIfb_mem * 1024;
2132 XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
2133 + xgi_video_info.heapstart);
2134 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2135 (int)(xgi_video_info.heapstart / 1024));
2137 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
2138 + xgi_video_info.video_size;
2139 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2141 /* TW: Now initialize the 310 series' command queue mode.
2142 * On 310/325, there are three queue modes available which
2143 * are chosen by setting bits 7:5 in SR26:
2144 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2145 * track of the queue, the FIFO, command parsing and so
2146 * on. This is the one comparable to the 300 series.
2147 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2148 * have to do queue management himself. Register 0x85c4 will
2149 * hold the location of the next free queue slot, 0x85c8
2150 * is the "queue read pointer" whose way of working is
2151 * unknown to me. Anyway, this mode would require a
2152 * translation of the MMIO commands to some kind of
2153 * accelerator assembly and writing these commands
2154 * to the memory location pointed to by 0x85c4.
2155 * We will not use this, as nobody knows how this
2156 * "assembly" works, and as it would require a complete
2157 * re-write of the accelerator code.
2158 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2159 * queue in AGP memory space.
2161 * SR26 bit 4 is called "Bypass H/W queue".
2162 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2163 * SR26 bit 0 resets the queue
2164 * Size of queue memory is encoded in bits 3:2 like this:
2169 * The queue location is to be written to 0x85C0.
2172 cmdq_baseport = (unsigned long *) (xgi_video_info.mmio_vbase
2173 + MMIO_QUEUE_PHYBASE);
2174 write_port = (unsigned long *) (xgi_video_info.mmio_vbase
2175 + MMIO_QUEUE_WRITEPORT);
2176 read_port = (unsigned long *) (xgi_video_info.mmio_vbase
2177 + MMIO_QUEUE_READPORT);
2179 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2181 agp_size = COMMAND_QUEUE_AREA_SIZE;
2184 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2185 agp_info = vzalloc(sizeof(*agp_info));
2186 agp_copy_info(agp_info);
2188 agp_backend_acquire();
2190 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
2193 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2196 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2197 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2198 /* TODO: Free AGP memory here */
2209 /* TW: Now select the queue mode */
2211 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2212 cmd_type = AGP_CMD_QUEUE;
2213 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2214 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2215 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2216 cmd_type = VM_CMD_QUEUE;
2217 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2219 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2220 cmd_type = MMIO_CMD;
2225 temp = XGI_CMD_QUEUE_SIZE_512k;
2228 temp = XGI_CMD_QUEUE_SIZE_1M;
2231 temp = XGI_CMD_QUEUE_SIZE_2M;
2234 temp = XGI_CMD_QUEUE_SIZE_4M;
2241 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2242 agp_info->aper_base, agp->physical, agp_size/1024);
2244 agp_phys = agp_info->aper_base + agp->physical;
2246 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2247 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2249 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2251 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2253 *write_port = *read_port;
2255 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2256 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2258 *cmdq_baseport = agp_phys;
2260 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2265 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2266 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2268 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2270 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2272 *write_port = *read_port;
2274 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2275 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2277 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2279 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2281 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2282 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2287 /* printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); */
2288 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2289 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2290 * enough. Reserve memory in any way.
2292 /* FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; */
2293 /* FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; */
2295 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); */
2296 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); */
2298 /* FIXME *write_port = *read_port; */
2300 /* FIXME *//* TW: Set Auto_Correction bit */
2301 /* FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); */
2302 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); */
2304 /* FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; */
2306 /* FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; */
2308 /* FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", */
2309 /* FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); */
2313 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2314 top of the videoRAM, right below the TB memory area (if used). */
2315 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2316 XGIfb_heap_end -= XGIfb_hwcursor_size;
2317 XGIfb_heap_size -= XGIfb_hwcursor_size;
2318 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2320 XGIfb_caps |= HW_CURSOR_CAP;
2322 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2323 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2326 XGIfb_heap.poha_chain = NULL;
2327 XGIfb_heap.poh_freelist = NULL;
2329 poh = XGIfb_poh_new_node();
2334 poh->poh_next = &XGIfb_heap.oh_free;
2335 poh->poh_prev = &XGIfb_heap.oh_free;
2336 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2337 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2339 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2340 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2341 (unsigned int) poh->size / 1024);
2343 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2344 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2346 XGIfb_heap.oh_free.poh_next = poh;
2347 XGIfb_heap.oh_free.poh_prev = poh;
2348 XGIfb_heap.oh_free.size = 0;
2349 XGIfb_heap.max_freesize = poh->size;
2351 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2352 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2353 XGIfb_heap.oh_used.size = SENTINEL;
2358 static XGI_OH *XGIfb_poh_new_node(void)
2365 if (XGIfb_heap.poh_freelist == NULL) {
2366 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2370 poha->poha_next = XGIfb_heap.poha_chain;
2371 XGIfb_heap.poha_chain = poha;
2373 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
2376 poh = &poha->aoh[0];
2377 for (i = cOhs - 1; i != 0; i--) {
2378 poh->poh_next = poh + 1;
2382 poh->poh_next = NULL;
2383 XGIfb_heap.poh_freelist = &poha->aoh[0];
2386 poh = XGIfb_heap.poh_freelist;
2387 XGIfb_heap.poh_freelist = poh->poh_next;
2392 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2398 if (size > XGIfb_heap.max_freesize) {
2399 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2400 (unsigned int) size / 1024);
2404 pohThis = XGIfb_heap.oh_free.poh_next;
2406 while (pohThis != &XGIfb_heap.oh_free) {
2407 if (size <= pohThis->size) {
2411 pohThis = pohThis->poh_next;
2415 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2416 (unsigned int) size / 1024);
2420 if (size == pohThis->size) {
2422 XGIfb_delete_node(pohThis);
2424 pohRoot = XGIfb_poh_new_node();
2426 if (pohRoot == NULL)
2429 pohRoot->offset = pohThis->offset;
2430 pohRoot->size = size;
2432 pohThis->offset += size;
2433 pohThis->size -= size;
2436 XGIfb_heap.max_freesize -= size;
2438 pohThis = &XGIfb_heap.oh_used;
2439 XGIfb_insert_node(pohThis, pohRoot);
2444 static void XGIfb_delete_node(XGI_OH *poh)
2449 poh_prev = poh->poh_prev;
2450 poh_next = poh->poh_next;
2452 poh_prev->poh_next = poh_next;
2453 poh_next->poh_prev = poh_prev;
2457 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2461 pohTemp = pohList->poh_next;
2463 pohList->poh_next = poh;
2464 pohTemp->poh_prev = poh;
2466 poh->poh_prev = pohList;
2467 poh->poh_next = pohTemp;
2470 static XGI_OH *XGIfb_poh_free(unsigned long base)
2476 unsigned long ulUpper;
2477 unsigned long ulLower;
2480 poh_freed = XGIfb_heap.oh_used.poh_next;
2482 while (poh_freed != &XGIfb_heap.oh_used) {
2483 if (poh_freed->offset == base) {
2488 poh_freed = poh_freed->poh_next;
2494 XGIfb_heap.max_freesize += poh_freed->size;
2496 poh_prev = poh_next = NULL;
2497 ulUpper = poh_freed->offset + poh_freed->size;
2498 ulLower = poh_freed->offset;
2500 pohThis = XGIfb_heap.oh_free.poh_next;
2502 while (pohThis != &XGIfb_heap.oh_free) {
2503 if (pohThis->offset == ulUpper)
2505 else if ((pohThis->offset + pohThis->size) == ulLower)
2508 pohThis = pohThis->poh_next;
2511 XGIfb_delete_node(poh_freed);
2513 if (poh_prev && poh_next) {
2514 poh_prev->size += (poh_freed->size + poh_next->size);
2515 XGIfb_delete_node(poh_next);
2516 XGIfb_free_node(poh_freed);
2517 XGIfb_free_node(poh_next);
2522 poh_prev->size += poh_freed->size;
2523 XGIfb_free_node(poh_freed);
2528 poh_next->size += poh_freed->size;
2529 poh_next->offset = poh_freed->offset;
2530 XGIfb_free_node(poh_freed);
2534 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2539 static void XGIfb_free_node(XGI_OH *poh)
2544 poh->poh_next = XGIfb_heap.poh_freelist;
2545 XGIfb_heap.poh_freelist = poh;
2549 void XGI_malloc(struct XGI_memreq *req)
2553 poh = XGIfb_poh_allocate(req->size);
2558 DPRINTK("XGIfb: Video RAM allocation failed\n");
2560 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2561 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2563 req->offset = poh->offset;
2564 req->size = poh->size;
2569 void XGI_free(unsigned long base)
2573 poh = XGIfb_poh_free(base);
2576 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2577 (unsigned int) base);
2581 /* --------------------- SetMode routines ------------------------- */
2583 static void XGIfb_pre_setmode(void)
2585 u8 cr30 = 0, cr31 = 0;
2587 inXGIIDXREG(XGICR, 0x31, cr31);
2590 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2592 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2593 cr31 |= XGI_DRIVER_MODE;
2596 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2597 cr31 |= XGI_DRIVER_MODE;
2600 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2601 cr30 = (XGI_VB_OUTPUT_HIVISION
2602 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2603 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2604 cr30 = (XGI_VB_OUTPUT_SVIDEO
2605 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2606 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2607 cr30 = (XGI_VB_OUTPUT_COMPOSITE
2608 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2609 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2610 cr30 = (XGI_VB_OUTPUT_SCART
2611 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2612 cr31 |= XGI_DRIVER_MODE;
2614 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2619 default: /* disable CRT2 */
2621 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2624 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2625 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2626 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2628 if (xgi_video_info.accel)
2633 static void XGIfb_post_setmode(void)
2636 unsigned char doit = 1;
2638 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2639 outXGIIDXREG(XGICR, 0x13, 0x00);
2640 setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
2643 if (xgi_video_info.video_bpp == 8) {
2644 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2645 if ((xgi_video_info.hasVB == HASVB_LVDS)
2646 || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2649 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2650 if (xgi_video_info.disp_state & DISPTYPE_LCD)
2654 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2655 if (xgi_video_info.hasVB != HASVB_NONE) {
2656 inXGIIDXREG(XGIPART1, 0x00, reg);
2658 if ((reg & 0x50) == 0x10)
2665 inXGIIDXREG(XGICR, 0x17, reg);
2666 if ((XGIfb_crt1off) && (doit))
2670 outXGIIDXREG(XGICR, 0x17, reg);
2672 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2674 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
2677 inXGIIDXREG(XGIPART4, 0x01, reg);
2679 if (reg < 0xB0) { /* Set filter for XGI301 */
2681 switch (xgi_video_info.video_width) {
2683 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2686 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2689 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2692 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2699 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2701 if (xgi_video_info.TV_type == TVMODE_NTSC) {
2703 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2705 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2707 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2709 } else if (xgi_video_info.TV_plug
2710 == TVPLUG_COMPOSITE) {
2712 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2714 switch (xgi_video_info.video_width) {
2716 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2717 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2718 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2719 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2722 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2723 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2724 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2725 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2728 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2729 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2730 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2731 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2736 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2738 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2740 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2742 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2744 } else if (xgi_video_info.TV_plug
2745 == TVPLUG_COMPOSITE) {
2747 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2749 switch (xgi_video_info.video_width) {
2751 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2752 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2753 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2754 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2757 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2758 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2759 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2760 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2763 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2764 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2765 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2766 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2772 if ((filter >= 0) && (filter <= 7)) {
2773 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2774 XGI_TV_filter[filter_tb].filter[filter][0],
2775 XGI_TV_filter[filter_tb].filter[filter][1],
2776 XGI_TV_filter[filter_tb].filter[filter][2],
2777 XGI_TV_filter[filter_tb].filter[filter][3]
2782 (XGI_TV_filter[filter_tb].filter[filter][0]));
2786 (XGI_TV_filter[filter_tb].filter[filter][1]));
2790 (XGI_TV_filter[filter_tb].filter[filter][2]));
2794 (XGI_TV_filter[filter_tb].filter[filter][3]));
2803 XGIINITSTATIC int __init XGIfb_setup(char *options)
2807 xgi_video_info.refresh_rate = 0;
2809 printk(KERN_INFO "XGIfb: Options %s\n", options);
2811 if (!options || !*options)
2814 while ((this_opt = strsep(&options, ",")) != NULL) {
2819 if (!strncmp(this_opt, "mode:", 5)) {
2820 XGIfb_search_mode(this_opt + 5);
2821 } else if (!strncmp(this_opt, "vesa:", 5)) {
2822 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2823 } else if (!strncmp(this_opt, "mode:", 5)) {
2824 XGIfb_search_mode(this_opt + 5);
2825 } else if (!strncmp(this_opt, "vesa:", 5)) {
2826 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2827 } else if (!strncmp(this_opt, "vrate:", 6)) {
2828 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2829 } else if (!strncmp(this_opt, "rate:", 5)) {
2830 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2831 } else if (!strncmp(this_opt, "off", 3)) {
2833 } else if (!strncmp(this_opt, "crt1off", 7)) {
2835 } else if (!strncmp(this_opt, "filter:", 7)) {
2836 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2837 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2838 XGIfb_search_crt2type(this_opt + 14);
2839 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2840 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2841 } else if (!strncmp(this_opt, "tvmode:", 7)) {
2842 XGIfb_search_tvstd(this_opt + 7);
2843 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2844 XGIfb_search_tvstd(this_opt + 7);
2845 } else if (!strncmp(this_opt, "mem:", 4)) {
2846 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2847 } else if (!strncmp(this_opt, "dstn", 4)) {
2849 /* TW: DSTN overrules forcecrt2type */
2850 XGIfb_crt2type = DISPTYPE_LCD;
2851 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2852 XGIfb_search_queuemode(this_opt + 10);
2853 } else if (!strncmp(this_opt, "pdc:", 4)) {
2854 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2855 if (XGIfb_pdc & ~0x3c) {
2856 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2859 } else if (!strncmp(this_opt, "noaccel", 7)) {
2861 } else if (!strncmp(this_opt, "noypan", 6)) {
2863 } else if (!strncmp(this_opt, "userom:", 7)) {
2864 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2865 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2866 /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2868 XGIfb_search_mode(this_opt);
2869 /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2872 /* TW: Acceleration only with MMIO mode */
2873 if ((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2877 /* TW: Panning only with acceleration */
2878 if (XGIfb_accel == 0)
2882 printk("\nxgifb: outa xgifb_setup 3450");
2886 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
2888 void __iomem *rom_address;
2889 unsigned char *rom_copy;
2892 rom_address = pci_map_rom(dev, &rom_size);
2893 if (rom_address == NULL)
2896 rom_copy = vzalloc(XGIFB_ROM_SIZE);
2897 if (rom_copy == NULL)
2900 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
2901 memcpy_fromio(rom_copy, rom_address, rom_size);
2904 pci_unmap_rom(dev, rom_address);
2908 static int __devinit xgifb_probe(struct pci_dev *pdev,
2909 const struct pci_device_id *ent)
2919 XGIfb_registered = 0;
2921 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2922 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2926 xgi_video_info.chip_id = pdev->device;
2927 pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2928 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2929 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2930 XGIvga_enabled = reg16 & 0x01;
2932 xgi_video_info.pcibus = pdev->bus->number;
2933 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2934 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2935 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2936 xgi_video_info.subsysdevice = pdev->subsystem_device;
2938 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2939 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2940 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2941 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2942 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2943 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2944 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2945 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2947 if (pci_enable_device(pdev)) {
2952 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2954 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2955 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2957 if (reg1 != 0xa1) { /*I/O error */
2958 printk("\nXGIfb: I/O error!!!");
2963 switch (xgi_video_info.chip_id) {
2964 case PCI_DEVICE_ID_XG_20:
2965 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2966 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2967 if (CR48&GPIOG_READ)
2968 xgi_video_info.chip = XG21;
2970 xgi_video_info.chip = XG20;
2971 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2972 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2974 case PCI_DEVICE_ID_XG_40:
2975 xgi_video_info.chip = XG40;
2976 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2977 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2979 case PCI_DEVICE_ID_XG_41:
2980 xgi_video_info.chip = XG41;
2981 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2982 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2984 case PCI_DEVICE_ID_XG_42:
2985 xgi_video_info.chip = XG42;
2986 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2987 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2989 case PCI_DEVICE_ID_XG_27:
2990 xgi_video_info.chip = XG27;
2991 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2992 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2999 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
3000 XGIhw_ext.jChipType = xgi_video_info.chip;
3002 switch (xgi_video_info.chip) {
3010 XGIhw_ext.bIntegratedMMEnabled = 1;
3016 XGIhw_ext.pDevice = NULL;
3017 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
3018 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
3019 if (XGIhw_ext.pjVirtualRomBase)
3020 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
3022 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3024 XGIhw_ext.pjVirtualRomBase = NULL;
3025 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3027 XGIhw_ext.pjCustomizedROMImage = NULL;
3028 XGIhw_ext.bSkipDramSizing = 0;
3029 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3030 /* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
3031 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3033 XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
3034 if (XGIhw_ext.pSR == NULL) {
3035 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3039 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3041 XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
3042 if (XGIhw_ext.pCR == NULL) {
3043 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3047 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3049 if (!XGIvga_enabled) {
3050 /* Mapping Max FB Size for 315 Init */
3051 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3052 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3054 printk("XGIfb: XGIInit() ...");
3055 /* XGIInitNewt for LINUXBIOS only */
3056 if (XGIInitNew(&XGIhw_ext))
3062 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3068 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3069 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3071 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3073 /* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
3074 /* Set SR13 ,14 temporarily for UDtech */
3075 outXGIIDXREG(XGISR, 0x13, 0x45);
3076 outXGIIDXREG(XGISR, 0x14, 0x51);
3081 if (XGIfb_get_dram_size()) {
3082 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3087 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3088 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3089 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3090 /* Enable 2D accelerator engine */
3091 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3094 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3096 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
3097 printk("unable request memory size %x", xgi_video_info.video_size);
3098 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3099 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3104 if (!request_mem_region(xgi_video_info.mmio_base,
3105 xgi_video_info.mmio_size,
3107 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3112 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3113 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3114 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
3115 xgi_video_info.mmio_size);
3117 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3118 xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
3120 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3121 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
3122 xgi_video_info.mmio_size / 1024);
3123 printk("XGIfb: XGIInitNew() ...");
3124 if (XGIInitNew(&XGIhw_ext))
3129 if (XGIfb_heap_init())
3130 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3132 xgi_video_info.mtrr = (unsigned int) 0;
3134 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3135 xgi_video_info.hasVB = HASVB_NONE;
3136 if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
3137 xgi_video_info.hasVB = HASVB_NONE;
3138 } else if (xgi_video_info.chip == XG21) {
3139 inXGIIDXREG(XGICR, 0x38, CR38);
3140 if ((CR38&0xE0) == 0xC0) {
3141 xgi_video_info.disp_state = DISPTYPE_LCD;
3142 if (!XGIfb_GetXG21LVDSData()) {
3144 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3145 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3146 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3147 XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
3151 } else if ((CR38&0xE0) == 0x60) {
3152 xgi_video_info.hasVB = HASVB_CHRONTEL;
3154 xgi_video_info.hasVB = HASVB_NONE;
3157 XGIfb_get_VB_type();
3160 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3162 XGIhw_ext.ulExternalChip = 0;
3164 switch (xgi_video_info.hasVB) {
3166 inXGIIDXREG(XGIPART4, 0x01, reg);
3168 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3169 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3170 } else if (reg >= 0xD0) {
3171 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3172 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
3174 /* else if (reg >= 0xB0) {
3175 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3176 inXGIIDXREG(XGIPART4, 0x23, reg1);
3177 printk("XGIfb: XGI301B bridge detected\n");
3180 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3181 printk("XGIfb: XGI301 bridge detected\n");
3185 inXGIIDXREG(XGIPART4, 0x01, reg);
3187 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3188 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3189 } else if (reg >= 0xD0) {
3190 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3191 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3192 } else if (reg >= 0xB0) {
3193 inXGIIDXREG(XGIPART4, 0x23, reg1);
3195 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3198 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3199 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3203 XGIhw_ext.ulExternalChip = 0x1;
3204 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3206 case HASVB_TRUMPION:
3207 XGIhw_ext.ulExternalChip = 0x2;
3208 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3210 case HASVB_CHRONTEL:
3211 XGIhw_ext.ulExternalChip = 0x4;
3212 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3214 case HASVB_LVDS_CHRONTEL:
3215 XGIhw_ext.ulExternalChip = 0x5;
3216 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3219 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3223 if (xgi_video_info.hasVB != HASVB_NONE)
3226 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3228 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3230 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3232 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3235 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3237 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3239 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3243 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3247 XGIfb_detectedpdc = 0;
3249 XGIfb_detectedlcda = 0xff;
3252 /* TW: Try to find about LCDA */
3254 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3255 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3256 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
3258 inXGIIDXREG(XGICR, 0x34, tmp);
3260 /* Currently on LCDA? (Some BIOSes leave CR38) */
3261 inXGIIDXREG(XGICR, 0x38, tmp);
3262 if ((tmp & 0x03) == 0x03) {
3263 /* XGI_Pr.XGI_UseLCDA = 1; */
3265 /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
3266 inXGIIDXREG(XGICR, 0x35, tmp);
3268 /* XGI_Pr.XGI_UseLCDA = 1; */
3270 inXGIIDXREG(XGICR, 0x30, tmp);
3272 inXGIIDXREG(XGIPART1, 0x13, tmp);
3274 /* XGI_Pr.XGI_UseLCDA = 1; */
3285 if (xgifb_mode_idx >= 0)
3286 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3288 if (xgifb_mode_idx < 0) {
3289 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3291 xgifb_mode_idx = DEFAULT_LCDMODE;
3292 if (xgi_video_info.chip == XG21)
3293 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3296 xgifb_mode_idx = DEFAULT_TVMODE;
3299 xgifb_mode_idx = DEFAULT_MODE;
3304 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3306 if (xgi_video_info.refresh_rate == 0)
3307 xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
3308 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
3309 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3310 xgi_video_info.refresh_rate = 60;
3313 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3314 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3315 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3316 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3317 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3318 switch (xgi_video_info.video_bpp) {
3320 xgi_video_info.DstColor = 0x0000;
3321 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3322 xgi_video_info.video_cmap_len = 256;
3325 xgi_video_info.DstColor = 0x8000;
3326 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3327 xgi_video_info.video_cmap_len = 16;
3330 xgi_video_info.DstColor = 0xC000;
3331 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3332 xgi_video_info.video_cmap_len = 16;
3335 xgi_video_info.video_cmap_len = 16;
3336 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3340 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3341 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3342 xgi_video_info.refresh_rate);
3344 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3345 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3346 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3348 XGIfb_bpp_to_var(&default_var);
3350 default_var.pixclock = (u32) (1000000000 /
3351 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3352 XGIfb_mode_no, XGIfb_rate_idx));
3354 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3355 XGIfb_mode_no, XGIfb_rate_idx,
3356 &default_var.left_margin, &default_var.right_margin,
3357 &default_var.upper_margin, &default_var.lower_margin,
3358 &default_var.hsync_len, &default_var.vsync_len,
3359 &default_var.sync, &default_var.vmode)) {
3361 if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3362 default_var.yres <<= 1;
3363 default_var.yres_virtual <<= 1;
3364 } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3365 default_var.pixclock >>= 1;
3366 default_var.yres >>= 1;
3367 default_var.yres_virtual >>= 1;
3372 xgi_video_info.accel = 0;
3374 xgi_video_info.accel = -1;
3375 default_var.accel_flags |= FB_ACCELF_TEXT;
3379 fb_info->flags = FBINFO_FLAG_DEFAULT;
3380 fb_info->var = default_var;
3381 fb_info->fix = XGIfb_fix;
3382 fb_info->par = &xgi_video_info;
3383 fb_info->screen_base = xgi_video_info.video_vbase;
3384 fb_info->fbops = &XGIfb_ops;
3385 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3386 fb_info->pseudo_palette = pseudo_palette;
3388 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3391 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3392 (unsigned int) xgi_video_info.video_size,
3393 MTRR_TYPE_WRCOMB, 1);
3394 if (xgi_video_info.mtrr)
3395 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3398 if (register_framebuffer(fb_info) < 0) {
3403 XGIfb_registered = 1;
3405 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3406 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3415 iounmap(xgi_video_info.mmio_vbase);
3416 iounmap(xgi_video_info.video_vbase);
3417 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
3419 release_mem_region(xgi_video_info.video_base,
3420 xgi_video_info.video_size);
3422 vfree(XGIhw_ext.pjVirtualRomBase);
3423 vfree(XGIhw_ext.pSR);
3424 vfree(XGIhw_ext.pCR);
3425 framebuffer_release(fb_info);
3429 /*****************************************************/
3430 /* PCI DEVICE HANDLING */
3431 /*****************************************************/
3433 static void __devexit xgifb_remove(struct pci_dev *pdev)
3435 unregister_framebuffer(fb_info);
3436 iounmap(xgi_video_info.mmio_vbase);
3437 iounmap(xgi_video_info.video_vbase);
3438 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
3439 release_mem_region(xgi_video_info.video_base,
3440 xgi_video_info.video_size);
3441 vfree(XGIhw_ext.pjVirtualRomBase);
3442 framebuffer_release(fb_info);
3443 pci_set_drvdata(pdev, NULL);
3446 static struct pci_driver xgifb_driver = {
3448 .id_table = xgifb_pci_table,
3449 .probe = xgifb_probe,
3450 .remove = __devexit_p(xgifb_remove)
3453 XGIINITSTATIC int __init xgifb_init(void)
3455 char *option = NULL;
3457 if (fb_get_options("xgifb", &option))
3459 XGIfb_setup(option);
3461 return pci_register_driver(&xgifb_driver);
3465 module_init(xgifb_init);
3468 /*****************************************************/
3470 /*****************************************************/
3474 static char *mode = NULL;
3475 static int vesa = 0;
3476 static unsigned int rate = 0;
3477 static unsigned int mem = 0;
3478 static char *forcecrt2type = NULL;
3479 static int forcecrt1 = -1;
3480 static int pdc = -1;
3481 static int pdc1 = -1;
3482 static int noaccel = -1;
3483 static int noypan = -1;
3484 static int nomax = -1;
3485 static int userom = -1;
3486 static int useoem = -1;
3487 static char *tvstandard = NULL;
3488 static int nocrt2rate = 0;
3489 static int scalelcd = -1;
3490 static char *specialtiming = NULL;
3491 static int lvdshl = -1;
3492 static int tvxposoffset = 0, tvyposoffset = 0;
3493 #if !defined(__i386__) && !defined(__x86_64__)
3494 static int resetcard = 0;
3495 static int videoram = 0;
3498 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3499 MODULE_LICENSE("GPL");
3500 MODULE_AUTHOR("XGITECH , Others");
3502 module_param(mem, int, 0);
3503 module_param(noaccel, int, 0);
3504 module_param(noypan, int, 0);
3505 module_param(nomax, int, 0);
3506 module_param(userom, int, 0);
3507 module_param(useoem, int, 0);
3508 module_param(mode, charp, 0);
3509 module_param(vesa, int, 0);
3510 module_param(rate, int, 0);
3511 module_param(forcecrt1, int, 0);
3512 module_param(forcecrt2type, charp, 0);
3513 module_param(scalelcd, int, 0);
3514 module_param(pdc, int, 0);
3515 module_param(pdc1, int, 0);
3516 module_param(specialtiming, charp, 0);
3517 module_param(lvdshl, int, 0);
3518 module_param(tvstandard, charp, 0);
3519 module_param(tvxposoffset, int, 0);
3520 module_param(tvyposoffset, int, 0);
3521 module_param(filter, int, 0);
3522 module_param(nocrt2rate, int, 0);
3523 #if !defined(__i386__) && !defined(__x86_64__)
3524 module_param(resetcard, int, 0);
3525 module_param(videoram, int, 0);
3528 MODULE_PARM_DESC(mem,
3529 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3530 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3531 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3532 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3533 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3534 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3535 "for XFree86 4.x/X.org 6.7 and later.\n");
3537 MODULE_PARM_DESC(noaccel,
3538 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3541 MODULE_PARM_DESC(noypan,
3542 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3543 "will be performed by redrawing the screen. (default: 0)\n");
3545 MODULE_PARM_DESC(nomax,
3546 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3547 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3548 "this is set to anything other than 0, xgifb will not do this and thereby\n"
3549 "enable the user to positively specify a virtual Y size of the screen using\n"
3550 "fbset. (default: 0)\n");
3552 MODULE_PARM_DESC(mode,
3553 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3554 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3555 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3556 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3558 MODULE_PARM_DESC(vesa,
3559 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3560 "0x117 (default: 0x0103)\n");
3562 MODULE_PARM_DESC(rate,
3563 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3564 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3565 "will be ignored (default: 60)\n");
3567 MODULE_PARM_DESC(forcecrt1,
3568 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
3569 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3570 "0=CRT1 OFF) (default: [autodetected])\n");
3572 MODULE_PARM_DESC(forcecrt2type,
3573 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3574 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3575 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3576 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3577 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3578 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3579 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3580 "depends on the very hardware in use. (default: [autodetected])\n");
3582 MODULE_PARM_DESC(scalelcd,
3583 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3584 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3585 "show black bars around the image, TMDS panels will probably do the scaling\n"
3586 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3588 MODULE_PARM_DESC(pdc,
3589 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3590 "should detect this correctly in most cases; however, sometimes this is not\n"
3591 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3592 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3593 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3594 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3596 MODULE_PARM_DESC(pdc1,
3597 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3598 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3599 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3600 "implemented yet.\n");
3602 MODULE_PARM_DESC(specialtiming,
3603 "\nPlease refer to documentation for more information on this option.\n");
3605 MODULE_PARM_DESC(lvdshl,
3606 "\nPlease refer to documentation for more information on this option.\n");
3608 MODULE_PARM_DESC(tvstandard,
3609 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3610 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3612 MODULE_PARM_DESC(tvxposoffset,
3613 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3616 MODULE_PARM_DESC(tvyposoffset,
3617 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3620 MODULE_PARM_DESC(filter,
3621 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3622 "(Possible values 0-7, default: [no filter])\n");
3624 MODULE_PARM_DESC(nocrt2rate,
3625 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3626 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3628 static int __init xgifb_init_module(void)
3630 printk("\nXGIfb_init_module");
3632 XGIfb_search_mode(mode);
3633 else if (vesa != -1)
3634 XGIfb_search_vesamode(vesa);
3636 return xgifb_init();
3639 static void __exit xgifb_remove_module(void)
3641 pci_unregister_driver(&xgifb_driver);
3642 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3645 module_init(xgifb_init_module);
3646 module_exit(xgifb_remove_module);
3648 #endif /* /MODULE */
3650 EXPORT_SYMBOL(XGI_malloc);
3651 EXPORT_SYMBOL(XGI_free);