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 u8 XGIfb_search_refresh_rate(unsigned int rate)
906 xres = XGIbios_mode[xgifb_mode_idx].xres;
907 yres = XGIbios_mode[xgifb_mode_idx].yres;
910 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
911 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres
913 if (XGIfb_vrate[i].refresh == rate) {
914 XGIfb_rate_idx = XGIfb_vrate[i].idx;
916 } else if (XGIfb_vrate[i].refresh > rate) {
917 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
918 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
919 rate, XGIfb_vrate[i].refresh);
920 XGIfb_rate_idx = XGIfb_vrate[i].idx;
921 xgi_video_info.refresh_rate
922 = XGIfb_vrate[i].refresh;
923 } else if (((rate - XGIfb_vrate[i - 1].refresh)
924 <= 2) && (XGIfb_vrate[i].idx
926 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
927 rate, XGIfb_vrate[i-1].refresh);
928 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
929 xgi_video_info.refresh_rate
930 = XGIfb_vrate[i - 1].refresh;
933 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
934 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
935 rate, XGIfb_vrate[i].refresh);
936 XGIfb_rate_idx = XGIfb_vrate[i].idx;
942 if (XGIfb_rate_idx > 0) {
943 return XGIfb_rate_idx;
946 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
951 static void XGIfb_search_tvstd(const char *name)
958 while (XGI_tvtype[i].type_no != -1) {
959 if (!strcmp(name, XGI_tvtype[i].name)) {
960 XGIfb_tvmode = XGI_tvtype[i].type_no;
967 /* ----------- FBDev related routines for all series ----------- */
969 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
971 switch (var->bits_per_pixel) {
973 var->red.offset = var->green.offset = var->blue.offset = 0;
974 var->red.length = var->green.length = var->blue.length = 6;
975 xgi_video_info.video_cmap_len = 256;
978 var->red.offset = 11;
980 var->green.offset = 5;
981 var->green.length = 6;
982 var->blue.offset = 0;
983 var->blue.length = 5;
984 var->transp.offset = 0;
985 var->transp.length = 0;
986 xgi_video_info.video_cmap_len = 16;
989 var->red.offset = 16;
991 var->green.offset = 8;
992 var->green.length = 8;
993 var->blue.offset = 0;
994 var->blue.length = 8;
995 var->transp.offset = 24;
996 var->transp.length = 8;
997 xgi_video_info.video_cmap_len = 16;
1002 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1003 struct fb_info *info)
1006 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1008 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1010 #if defined(__powerpc__)
1011 u8 sr_data, cr_data;
1013 unsigned int drate = 0, hrate = 0;
1016 /* unsigned char reg, reg1; */
1018 DEBUGPRN("Inside do_set_var");
1019 /* 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); */
1021 info->var.xres_virtual = var->xres_virtual;
1022 info->var.yres_virtual = var->yres_virtual;
1023 info->var.bits_per_pixel = var->bits_per_pixel;
1025 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1027 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1029 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1031 /* var->yres <<= 1; */
1034 if (!htotal || !vtotal) {
1035 DPRINTK("XGIfb: Invalid 'var' information\n");
1037 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1038 var->pixclock, htotal, vtotal);
1040 if (var->pixclock && htotal && vtotal) {
1041 drate = 1000000000 / var->pixclock;
1042 hrate = (drate * 1000) / htotal;
1043 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1046 xgi_video_info.refresh_rate = 60;
1049 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1050 var->xres, var->yres, var->bits_per_pixel, xgi_video_info.refresh_rate);
1052 old_mode = xgifb_mode_idx;
1055 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1056 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1057 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1058 && (XGIbios_mode[xgifb_mode_idx].yres
1060 && (XGIbios_mode[xgifb_mode_idx].bpp
1061 == var->bits_per_pixel)) {
1062 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1070 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1072 xgifb_mode_idx = -1;
1074 if (xgifb_mode_idx < 0) {
1075 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1076 var->yres, var->bits_per_pixel);
1077 xgifb_mode_idx = old_mode;
1081 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1082 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1083 xgi_video_info.refresh_rate = 60;
1088 XGIfb_pre_setmode();
1089 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1090 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1093 info->fix.line_length = ((info->var.xres_virtual
1094 * info->var.bits_per_pixel) >> 6);
1096 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1098 outXGIIDXREG(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1099 outXGIIDXREG(XGISR, 0x0E, (info->fix.line_length & 0xff00) >> 8);
1101 XGIfb_post_setmode();
1103 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1104 XGIbios_mode[xgifb_mode_idx].xres,
1105 XGIbios_mode[xgifb_mode_idx].yres,
1106 XGIbios_mode[xgifb_mode_idx].bpp,
1107 xgi_video_info.refresh_rate);
1109 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1110 xgi_video_info.video_vwidth = info->var.xres_virtual;
1111 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1112 xgi_video_info.video_vheight = info->var.yres_virtual;
1113 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1114 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1115 xgi_video_info.video_linelength = info->var.xres_virtual
1116 * (xgi_video_info.video_bpp >> 3);
1117 switch (xgi_video_info.video_bpp) {
1119 xgi_video_info.DstColor = 0x0000;
1120 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1121 xgi_video_info.video_cmap_len = 256;
1122 #if defined(__powerpc__)
1123 inXGIIDXREG(XGICR, 0x4D, cr_data);
1124 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1128 xgi_video_info.DstColor = 0x8000;
1129 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1130 #if defined(__powerpc__)
1131 inXGIIDXREG(XGICR, 0x4D, cr_data);
1132 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1134 xgi_video_info.video_cmap_len = 16;
1137 xgi_video_info.DstColor = 0xC000;
1138 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1139 xgi_video_info.video_cmap_len = 16;
1140 #if defined(__powerpc__)
1141 inXGIIDXREG(XGICR, 0x4D, cr_data);
1142 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1146 xgi_video_info.video_cmap_len = 16;
1147 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1151 XGIfb_bpp_to_var(var); /*update ARGB info*/
1152 DEBUGPRN("End of do_set_var");
1159 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1163 /* printk("Inside pan_var"); */
1165 if (var->xoffset > (var->xres_virtual - var->xres)) {
1166 /* printk("Pan: xo: %d xv %d xr %d\n",
1167 var->xoffset, var->xres_virtual, var->xres); */
1170 if (var->yoffset > (var->yres_virtual - var->yres)) {
1171 /* printk("Pan: yo: %d yv %d yr %d\n",
1172 var->yoffset, var->yres_virtual, var->yres); */
1175 base = var->yoffset * var->xres_virtual + var->xoffset;
1177 /* calculate base bpp dep. */
1178 switch (var->bits_per_pixel) {
1190 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1192 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1193 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1194 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1195 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1196 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1198 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1199 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1200 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1201 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1202 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1203 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1205 /* printk("End of pan_var"); */
1210 static int XGIfb_open(struct fb_info *info, int user)
1215 static int XGIfb_release(struct fb_info *info, int user)
1220 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1224 switch (var->bits_per_pixel) {
1238 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1239 unsigned blue, unsigned transp, struct fb_info *info)
1241 if (regno >= XGIfb_get_cmap_len(&info->var))
1244 switch (info->var.bits_per_pixel) {
1246 outXGIREG(XGIDACA, regno);
1247 outXGIREG(XGIDACD, (red >> 10));
1248 outXGIREG(XGIDACD, (green >> 10));
1249 outXGIREG(XGIDACD, (blue >> 10));
1250 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1251 outXGIREG(XGIDAC2A, regno);
1252 outXGIREG(XGIDAC2D, (red >> 8));
1253 outXGIREG(XGIDAC2D, (green >> 8));
1254 outXGIREG(XGIDAC2D, (blue >> 8));
1258 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1259 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1266 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1273 static int XGIfb_set_par(struct fb_info *info)
1277 /* printk("XGIfb: inside set_par\n"); */
1278 err = XGIfb_do_set_var(&info->var, 1, info);
1281 XGIfb_get_fix(&info->fix, -1, info);
1282 /* printk("XGIfb: end of set_par\n"); */
1286 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1288 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1290 unsigned int vtotal = 0;
1291 unsigned int drate = 0, hrate = 0;
1293 int refresh_rate, search_idx;
1295 DEBUGPRN("Inside check_var");
1297 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1298 vtotal = var->upper_margin + var->yres + var->lower_margin
1301 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1302 vtotal = var->upper_margin + var->yres + var->lower_margin
1305 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1306 vtotal = var->upper_margin + (var->yres / 2)
1307 + var->lower_margin + var->vsync_len;
1309 vtotal = var->upper_margin + var->yres + var->lower_margin
1312 if (!(htotal) || !(vtotal))
1313 XGIFAIL("XGIfb: no valid timing data");
1315 if (var->pixclock && htotal && vtotal) {
1316 drate = 1000000000 / var->pixclock;
1317 hrate = (drate * 1000) / htotal;
1318 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1320 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1321 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1322 __func__, var->pixclock, htotal, vtotal,
1323 __func__, drate, hrate, xgi_video_info.refresh_rate);
1325 xgi_video_info.refresh_rate = 60;
1329 if ((var->pixclock) && (htotal)) {
1330 drate = 1E12 / var->pixclock;
1331 hrate = drate / htotal;
1332 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1337 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1338 if ((var->xres == 1024) && (var->yres == 600))
1342 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1343 (XGIbios_mode[search_idx].xres <= var->xres)) {
1344 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1345 (XGIbios_mode[search_idx].yres == var->yres) &&
1346 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1347 if (XGIfb_validate_mode(search_idx) > 0) {
1357 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1358 var->xres, var->yres, var->bits_per_pixel);
1360 while (XGIbios_mode[search_idx].mode_no != 0) {
1362 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1363 (var->yres <= XGIbios_mode[search_idx].yres) &&
1364 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1365 if (XGIfb_validate_mode(search_idx) > 0) {
1373 var->xres = XGIbios_mode[search_idx].xres;
1374 var->yres = XGIbios_mode[search_idx].yres;
1375 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1376 var->xres, var->yres, var->bits_per_pixel);
1379 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1380 var->xres, var->yres, var->bits_per_pixel);
1385 /* TW: TODO: Check the refresh rate */
1387 /* Adapt RGB settings */
1388 XGIfb_bpp_to_var(var);
1390 /* Sanity check for offsets */
1391 if (var->xoffset < 0)
1393 if (var->yoffset < 0)
1397 if (var->xres != var->xres_virtual)
1398 var->xres_virtual = var->xres;
1399 if (var->yres != var->yres_virtual)
1400 var->yres_virtual = var->yres;
1402 /* TW: Now patch yres_virtual if we use panning */
1403 /* May I do this? */
1404 /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1405 /* if (var->yres_virtual <= var->yres) { */
1406 /* TW: Paranoia check */
1407 /* var->yres_virtual = var->yres; */
1411 /* Truncate offsets to maximum if too high */
1412 if (var->xoffset > var->xres_virtual - var->xres)
1413 var->xoffset = var->xres_virtual - var->xres - 1;
1415 if (var->yoffset > var->yres_virtual - var->yres)
1416 var->yoffset = var->yres_virtual - var->yres - 1;
1418 /* Set everything else to 0 */
1419 var->red.msb_right =
1420 var->green.msb_right =
1421 var->blue.msb_right =
1422 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1424 DEBUGPRN("end of check_var");
1429 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1430 struct fb_info *info)
1434 /* printk("\nInside pan_display:\n"); */
1436 if (var->xoffset > (var->xres_virtual - var->xres))
1438 if (var->yoffset > (var->yres_virtual - var->yres))
1441 if (var->vmode & FB_VMODE_YWRAP) {
1442 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1446 if (var->xoffset + info->var.xres > info->var.xres_virtual
1447 || var->yoffset + info->var.yres
1448 > info->var.yres_virtual)
1451 err = XGIfb_pan_var(var);
1455 info->var.xoffset = var->xoffset;
1456 info->var.yoffset = var->yoffset;
1457 if (var->vmode & FB_VMODE_YWRAP)
1458 info->var.vmode |= FB_VMODE_YWRAP;
1460 info->var.vmode &= ~FB_VMODE_YWRAP;
1462 /* printk("End of pan_display\n"); */
1467 static int XGIfb_blank(int blank, struct fb_info *info)
1471 inXGIIDXREG(XGICR, 0x17, reg);
1478 outXGIIDXREG(XGICR, 0x17, reg);
1479 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1480 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1484 /* ----------- FBDev related routines for all series ---------- */
1486 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1487 struct fb_info *info)
1489 DEBUGPRN("inside get_fix");
1490 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1492 strcpy(fix->id, myid);
1494 fix->smem_start = xgi_video_info.video_base;
1496 fix->smem_len = xgi_video_info.video_size;
1498 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1499 if (xgi_video_info.video_size > 0x1000000) {
1500 fix->smem_len = 0xD00000;
1501 } else if (xgi_video_info.video_size > 0x800000)
1502 fix->smem_len = 0x800000;
1504 fix->smem_len = 0x400000;
1506 fix->smem_len = XGIfb_mem * 1024;
1508 fix->type = video_type;
1510 if (xgi_video_info.video_bpp == 8)
1511 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1513 fix->visual = FB_VISUAL_DIRECTCOLOR;
1520 fix->line_length = xgi_video_info.video_linelength;
1521 fix->mmio_start = xgi_video_info.mmio_base;
1522 fix->mmio_len = xgi_video_info.mmio_size;
1523 if (xgi_video_info.chip >= XG40)
1524 fix->accel = FB_ACCEL_XGI_XABRE;
1526 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1528 DEBUGPRN("end of get_fix");
1532 static struct fb_ops XGIfb_ops = {
1533 .owner = THIS_MODULE,
1534 .fb_open = XGIfb_open,
1535 .fb_release = XGIfb_release,
1536 .fb_check_var = XGIfb_check_var,
1537 .fb_set_par = XGIfb_set_par,
1538 .fb_setcolreg = XGIfb_setcolreg,
1540 .fb_pan_display = XGIfb_pan_display,
1542 .fb_blank = XGIfb_blank,
1543 .fb_fillrect = cfb_fillrect,
1544 .fb_copyarea = cfb_copyarea,
1545 .fb_imageblit = cfb_imageblit,
1546 /* .fb_mmap = XGIfb_mmap, */
1549 /* ---------------- Chip generation dependent routines ---------------- */
1551 /* for XGI 315/550/650/740/330 */
1553 static int XGIfb_get_dram_size(void)
1559 /* xorg driver sets 32MB * 1 channel */
1560 if (xgi_video_info.chip == XG27)
1561 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1563 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1564 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1565 case XGI_DRAM_SIZE_1MB:
1566 xgi_video_info.video_size = 0x100000;
1568 case XGI_DRAM_SIZE_2MB:
1569 xgi_video_info.video_size = 0x200000;
1571 case XGI_DRAM_SIZE_4MB:
1572 xgi_video_info.video_size = 0x400000;
1574 case XGI_DRAM_SIZE_8MB:
1575 xgi_video_info.video_size = 0x800000;
1577 case XGI_DRAM_SIZE_16MB:
1578 xgi_video_info.video_size = 0x1000000;
1580 case XGI_DRAM_SIZE_32MB:
1581 xgi_video_info.video_size = 0x2000000;
1583 case XGI_DRAM_SIZE_64MB:
1584 xgi_video_info.video_size = 0x4000000;
1586 case XGI_DRAM_SIZE_128MB:
1587 xgi_video_info.video_size = 0x8000000;
1589 case XGI_DRAM_SIZE_256MB:
1590 xgi_video_info.video_size = 0x10000000;
1596 tmp = (reg & 0x0c) >> 2;
1597 switch (xgi_video_info.chip) {
1633 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1634 /* PLiad fixed for benchmarking and fb set */
1635 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1636 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1638 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1639 xgi_video_info.video_size, ChannelNum);
1644 static void XGIfb_detect_VB(void)
1648 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1650 switch (xgi_video_info.hasVB) {
1651 case HASVB_LVDS_CHRONTEL:
1652 case HASVB_CHRONTEL:
1656 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1660 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1662 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1671 if (XGIfb_crt2type != -1)
1672 /* TW: Override with option */
1673 xgi_video_info.disp_state = XGIfb_crt2type;
1674 else if (cr32 & XGI_VB_TV)
1675 xgi_video_info.disp_state = DISPTYPE_TV;
1676 else if (cr32 & XGI_VB_LCD)
1677 xgi_video_info.disp_state = DISPTYPE_LCD;
1678 else if (cr32 & XGI_VB_CRT2)
1679 xgi_video_info.disp_state = DISPTYPE_CRT2;
1681 xgi_video_info.disp_state = 0;
1683 if (XGIfb_tvplug != -1)
1684 /* PR/TW: Override with option */
1685 xgi_video_info.TV_plug = XGIfb_tvplug;
1686 else if (cr32 & XGI_VB_HIVISION) {
1687 xgi_video_info.TV_type = TVMODE_HIVISION;
1688 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1689 } else if (cr32 & XGI_VB_SVIDEO)
1690 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1691 else if (cr32 & XGI_VB_COMPOSITE)
1692 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1693 else if (cr32 & XGI_VB_SCART)
1694 xgi_video_info.TV_plug = TVPLUG_SCART;
1696 if (xgi_video_info.TV_type == 0) {
1697 /* TW: PAL/NTSC changed for 650 */
1698 if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
1701 inXGIIDXREG(XGICR, 0x38, temp);
1703 xgi_video_info.TV_type = TVMODE_PAL;
1705 xgi_video_info.TV_type = TVMODE_NTSC;
1709 inXGIIDXREG(XGICR, 0x79, temp);
1711 xgi_video_info.TV_type = TVMODE_PAL;
1713 xgi_video_info.TV_type = TVMODE_NTSC;
1717 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1718 if (XGIfb_forcecrt1 != -1) {
1719 if (XGIfb_forcecrt1)
1726 static void XGIfb_get_VB_type(void)
1730 if (!XGIfb_has_VB()) {
1731 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1732 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1733 case XGI310_EXTERNAL_CHIP_LVDS:
1734 xgi_video_info.hasVB = HASVB_LVDS;
1736 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1737 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1745 static int XGIfb_has_VB(void)
1749 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1750 switch (vb_chipid) {
1752 xgi_video_info.hasVB = HASVB_301;
1755 xgi_video_info.hasVB = HASVB_302;
1758 xgi_video_info.hasVB = HASVB_NONE;
1764 /* ------------------ Sensing routines ------------------ */
1766 /* TW: Determine and detect attached devices on XGI30x */
1767 int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1771 outXGIIDXREG(XGIPART4, 0x11, tempbl);
1772 temp = tempbh | tempcl;
1773 setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1774 for (i = 0; i < 10; i++)
1775 XGI_LongWait(&XGI_Pr);
1777 inXGIIDXREG(XGIPART4, 0x03, temp);
1783 void XGI_Sense30x(void)
1786 u8 testsvhs_tempbl, testsvhs_tempbh;
1787 u8 testsvhs_tempcl, testsvhs_tempch;
1788 u8 testcvbs_tempbl, testcvbs_tempbh;
1789 u8 testcvbs_tempcl, testcvbs_tempch;
1790 u8 testvga2_tempbl, testvga2_tempbh;
1791 u8 testvga2_tempcl, testvga2_tempch;
1794 inXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
1795 outXGIIDXREG(XGIPART4, 0x0d, (backupP4_0d | 0x04));
1797 testvga2_tempbh = 0x00;
1798 testvga2_tempbl = 0xd1;
1799 testsvhs_tempbh = 0x00;
1800 testsvhs_tempbl = 0xb9;
1801 testcvbs_tempbh = 0x00;
1802 testcvbs_tempbl = 0xb3;
1803 if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
1805 testvga2_tempbh = 0x01;
1806 testvga2_tempbl = 0x90;
1807 testsvhs_tempbh = 0x01;
1808 testsvhs_tempbl = 0x6b;
1809 testcvbs_tempbh = 0x01;
1810 testcvbs_tempbl = 0x74;
1811 if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
1812 || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
1813 testvga2_tempbh = 0x00;
1814 testvga2_tempbl = 0x00;
1815 testsvhs_tempbh = 0x02;
1816 testsvhs_tempbl = 0x00;
1817 testcvbs_tempbh = 0x01;
1818 testcvbs_tempbl = 0x00;
1821 if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
1823 inXGIIDXREG(XGIPART4, 0x01, myflag);
1824 if (myflag & 0x04) {
1825 testvga2_tempbh = 0x00;
1826 testvga2_tempbl = 0xfd;
1827 testsvhs_tempbh = 0x00;
1828 testsvhs_tempbl = 0xdd;
1829 testcvbs_tempbh = 0x00;
1830 testcvbs_tempbl = 0xee;
1833 if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
1834 == VB_CHIP_302LV)) {
1835 testvga2_tempbh = 0x00;
1836 testvga2_tempbl = 0x00;
1837 testvga2_tempch = 0x00;
1838 testvga2_tempcl = 0x00;
1839 testsvhs_tempch = 0x04;
1840 testsvhs_tempcl = 0x08;
1841 testcvbs_tempch = 0x08;
1842 testcvbs_tempcl = 0x08;
1844 testvga2_tempch = 0x0e;
1845 testvga2_tempcl = 0x08;
1846 testsvhs_tempch = 0x06;
1847 testsvhs_tempcl = 0x04;
1848 testcvbs_tempch = 0x08;
1849 testcvbs_tempcl = 0x04;
1852 if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
1853 || testvga2_tempbl) {
1854 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
1855 testvga2_tempcl, testvga2_tempch);
1857 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
1858 orXGIIDXREG(XGICR, 0x32, 0x10);
1862 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
1865 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
1866 /* TW: So we can be sure that there IS a SVHS output */
1867 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1868 orXGIIDXREG(XGICR, 0x32, 0x02);
1872 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
1873 testcvbs_tempcl, testcvbs_tempch);
1875 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
1876 /* TW: So we can be sure that there IS a CVBS output */
1877 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1878 orXGIIDXREG(XGICR, 0x32, 0x01);
1881 XGIDoSense(0, 0, 0, 0);
1883 outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
1886 /* ------------------------ Heap routines -------------------------- */
1888 static int XGIfb_heap_init(void)
1892 /* TW: The heap start is either set manually using the "mem" parameter, or
1893 * defaults as follows:
1894 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
1895 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
1896 * -) If 4MB or less is available, let it start at 4MB.
1897 * This is for avoiding a clash with X driver which uses the beginning
1898 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
1900 * The heap start can also be specified by parameter "mem" when starting the XGIfb
1901 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
1903 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
1904 if (xgi_video_info.video_size > 0x1000000)
1905 xgi_video_info.heapstart = 0xD00000;
1906 else if (xgi_video_info.video_size > 0x800000)
1907 xgi_video_info.heapstart = 0x800000;
1909 xgi_video_info.heapstart = 0x400000;
1911 xgi_video_info.heapstart = XGIfb_mem * 1024;
1913 XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
1914 + xgi_video_info.heapstart);
1915 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
1916 (int)(xgi_video_info.heapstart / 1024));
1918 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
1919 + xgi_video_info.video_size;
1920 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
1922 XGIfb_heap.poha_chain = NULL;
1923 XGIfb_heap.poh_freelist = NULL;
1925 poh = XGIfb_poh_new_node();
1930 poh->poh_next = &XGIfb_heap.oh_free;
1931 poh->poh_prev = &XGIfb_heap.oh_free;
1932 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
1933 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
1935 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
1936 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
1937 (unsigned int) poh->size / 1024);
1939 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
1940 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
1942 XGIfb_heap.oh_free.poh_next = poh;
1943 XGIfb_heap.oh_free.poh_prev = poh;
1944 XGIfb_heap.oh_free.size = 0;
1945 XGIfb_heap.max_freesize = poh->size;
1947 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
1948 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
1949 XGIfb_heap.oh_used.size = SENTINEL;
1954 static XGI_OH *XGIfb_poh_new_node(void)
1961 if (XGIfb_heap.poh_freelist == NULL) {
1962 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
1966 poha->poha_next = XGIfb_heap.poha_chain;
1967 XGIfb_heap.poha_chain = poha;
1969 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
1972 poh = &poha->aoh[0];
1973 for (i = cOhs - 1; i != 0; i--) {
1974 poh->poh_next = poh + 1;
1978 poh->poh_next = NULL;
1979 XGIfb_heap.poh_freelist = &poha->aoh[0];
1982 poh = XGIfb_heap.poh_freelist;
1983 XGIfb_heap.poh_freelist = poh->poh_next;
1988 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
1994 if (size > XGIfb_heap.max_freesize) {
1995 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
1996 (unsigned int) size / 1024);
2000 pohThis = XGIfb_heap.oh_free.poh_next;
2002 while (pohThis != &XGIfb_heap.oh_free) {
2003 if (size <= pohThis->size) {
2007 pohThis = pohThis->poh_next;
2011 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2012 (unsigned int) size / 1024);
2016 if (size == pohThis->size) {
2018 XGIfb_delete_node(pohThis);
2020 pohRoot = XGIfb_poh_new_node();
2022 if (pohRoot == NULL)
2025 pohRoot->offset = pohThis->offset;
2026 pohRoot->size = size;
2028 pohThis->offset += size;
2029 pohThis->size -= size;
2032 XGIfb_heap.max_freesize -= size;
2034 pohThis = &XGIfb_heap.oh_used;
2035 XGIfb_insert_node(pohThis, pohRoot);
2040 static void XGIfb_delete_node(XGI_OH *poh)
2045 poh_prev = poh->poh_prev;
2046 poh_next = poh->poh_next;
2048 poh_prev->poh_next = poh_next;
2049 poh_next->poh_prev = poh_prev;
2053 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2057 pohTemp = pohList->poh_next;
2059 pohList->poh_next = poh;
2060 pohTemp->poh_prev = poh;
2062 poh->poh_prev = pohList;
2063 poh->poh_next = pohTemp;
2066 static XGI_OH *XGIfb_poh_free(unsigned long base)
2072 unsigned long ulUpper;
2073 unsigned long ulLower;
2076 poh_freed = XGIfb_heap.oh_used.poh_next;
2078 while (poh_freed != &XGIfb_heap.oh_used) {
2079 if (poh_freed->offset == base) {
2084 poh_freed = poh_freed->poh_next;
2090 XGIfb_heap.max_freesize += poh_freed->size;
2092 poh_prev = poh_next = NULL;
2093 ulUpper = poh_freed->offset + poh_freed->size;
2094 ulLower = poh_freed->offset;
2096 pohThis = XGIfb_heap.oh_free.poh_next;
2098 while (pohThis != &XGIfb_heap.oh_free) {
2099 if (pohThis->offset == ulUpper)
2101 else if ((pohThis->offset + pohThis->size) == ulLower)
2104 pohThis = pohThis->poh_next;
2107 XGIfb_delete_node(poh_freed);
2109 if (poh_prev && poh_next) {
2110 poh_prev->size += (poh_freed->size + poh_next->size);
2111 XGIfb_delete_node(poh_next);
2112 XGIfb_free_node(poh_freed);
2113 XGIfb_free_node(poh_next);
2118 poh_prev->size += poh_freed->size;
2119 XGIfb_free_node(poh_freed);
2124 poh_next->size += poh_freed->size;
2125 poh_next->offset = poh_freed->offset;
2126 XGIfb_free_node(poh_freed);
2130 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2135 static void XGIfb_free_node(XGI_OH *poh)
2140 poh->poh_next = XGIfb_heap.poh_freelist;
2141 XGIfb_heap.poh_freelist = poh;
2145 void XGI_malloc(struct XGI_memreq *req)
2149 poh = XGIfb_poh_allocate(req->size);
2154 DPRINTK("XGIfb: Video RAM allocation failed\n");
2156 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2157 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2159 req->offset = poh->offset;
2160 req->size = poh->size;
2165 void XGI_free(unsigned long base)
2169 poh = XGIfb_poh_free(base);
2172 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2173 (unsigned int) base);
2177 /* --------------------- SetMode routines ------------------------- */
2179 static void XGIfb_pre_setmode(void)
2181 u8 cr30 = 0, cr31 = 0;
2183 inXGIIDXREG(XGICR, 0x31, cr31);
2186 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2188 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2189 cr31 |= XGI_DRIVER_MODE;
2192 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2193 cr31 |= XGI_DRIVER_MODE;
2196 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2197 cr30 = (XGI_VB_OUTPUT_HIVISION
2198 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2199 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2200 cr30 = (XGI_VB_OUTPUT_SVIDEO
2201 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2202 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2203 cr30 = (XGI_VB_OUTPUT_COMPOSITE
2204 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2205 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2206 cr30 = (XGI_VB_OUTPUT_SCART
2207 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2208 cr31 |= XGI_DRIVER_MODE;
2210 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2215 default: /* disable CRT2 */
2217 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2220 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2221 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2222 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2225 static void XGIfb_post_setmode(void)
2228 unsigned char doit = 1;
2230 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2231 outXGIIDXREG(XGICR, 0x13, 0x00);
2232 setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
2235 if (xgi_video_info.video_bpp == 8) {
2236 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2237 if ((xgi_video_info.hasVB == HASVB_LVDS)
2238 || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2241 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2242 if (xgi_video_info.disp_state & DISPTYPE_LCD)
2246 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2247 if (xgi_video_info.hasVB != HASVB_NONE) {
2248 inXGIIDXREG(XGIPART1, 0x00, reg);
2250 if ((reg & 0x50) == 0x10)
2257 inXGIIDXREG(XGICR, 0x17, reg);
2258 if ((XGIfb_crt1off) && (doit))
2262 outXGIIDXREG(XGICR, 0x17, reg);
2264 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2266 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
2269 inXGIIDXREG(XGIPART4, 0x01, reg);
2271 if (reg < 0xB0) { /* Set filter for XGI301 */
2273 switch (xgi_video_info.video_width) {
2275 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2278 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2281 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2284 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2291 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2293 if (xgi_video_info.TV_type == TVMODE_NTSC) {
2295 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2297 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2299 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2301 } else if (xgi_video_info.TV_plug
2302 == TVPLUG_COMPOSITE) {
2304 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2306 switch (xgi_video_info.video_width) {
2308 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2309 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2310 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2311 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2314 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2315 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2316 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2317 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2320 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2321 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2322 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2323 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2328 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2330 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2332 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2334 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2336 } else if (xgi_video_info.TV_plug
2337 == TVPLUG_COMPOSITE) {
2339 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2341 switch (xgi_video_info.video_width) {
2343 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2344 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2345 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2346 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2349 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2350 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2351 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2352 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2355 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2356 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2357 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2358 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2364 if ((filter >= 0) && (filter <= 7)) {
2365 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2366 XGI_TV_filter[filter_tb].filter[filter][0],
2367 XGI_TV_filter[filter_tb].filter[filter][1],
2368 XGI_TV_filter[filter_tb].filter[filter][2],
2369 XGI_TV_filter[filter_tb].filter[filter][3]
2374 (XGI_TV_filter[filter_tb].filter[filter][0]));
2378 (XGI_TV_filter[filter_tb].filter[filter][1]));
2382 (XGI_TV_filter[filter_tb].filter[filter][2]));
2386 (XGI_TV_filter[filter_tb].filter[filter][3]));
2395 XGIINITSTATIC int __init XGIfb_setup(char *options)
2399 xgi_video_info.refresh_rate = 0;
2401 printk(KERN_INFO "XGIfb: Options %s\n", options);
2403 if (!options || !*options)
2406 while ((this_opt = strsep(&options, ",")) != NULL) {
2411 if (!strncmp(this_opt, "mode:", 5)) {
2412 XGIfb_search_mode(this_opt + 5);
2413 } else if (!strncmp(this_opt, "vesa:", 5)) {
2414 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2415 } else if (!strncmp(this_opt, "mode:", 5)) {
2416 XGIfb_search_mode(this_opt + 5);
2417 } else if (!strncmp(this_opt, "vesa:", 5)) {
2418 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2419 } else if (!strncmp(this_opt, "vrate:", 6)) {
2420 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2421 } else if (!strncmp(this_opt, "rate:", 5)) {
2422 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2423 } else if (!strncmp(this_opt, "off", 3)) {
2425 } else if (!strncmp(this_opt, "crt1off", 7)) {
2427 } else if (!strncmp(this_opt, "filter:", 7)) {
2428 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2429 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2430 XGIfb_search_crt2type(this_opt + 14);
2431 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2432 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2433 } else if (!strncmp(this_opt, "tvmode:", 7)) {
2434 XGIfb_search_tvstd(this_opt + 7);
2435 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2436 XGIfb_search_tvstd(this_opt + 7);
2437 } else if (!strncmp(this_opt, "mem:", 4)) {
2438 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2439 } else if (!strncmp(this_opt, "dstn", 4)) {
2441 /* TW: DSTN overrules forcecrt2type */
2442 XGIfb_crt2type = DISPTYPE_LCD;
2443 } else if (!strncmp(this_opt, "pdc:", 4)) {
2444 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2445 if (XGIfb_pdc & ~0x3c) {
2446 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2449 } else if (!strncmp(this_opt, "noypan", 6)) {
2451 } else if (!strncmp(this_opt, "userom:", 7)) {
2452 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2453 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2454 /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2456 XGIfb_search_mode(this_opt);
2457 /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2460 /* TW: Panning only with acceleration */
2464 printk("\nxgifb: outa xgifb_setup 3450");
2468 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
2470 void __iomem *rom_address;
2471 unsigned char *rom_copy;
2474 rom_address = pci_map_rom(dev, &rom_size);
2475 if (rom_address == NULL)
2478 rom_copy = vzalloc(XGIFB_ROM_SIZE);
2479 if (rom_copy == NULL)
2482 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
2483 memcpy_fromio(rom_copy, rom_address, rom_size);
2486 pci_unmap_rom(dev, rom_address);
2490 static int __devinit xgifb_probe(struct pci_dev *pdev,
2491 const struct pci_device_id *ent)
2501 XGIfb_registered = 0;
2503 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2504 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2508 xgi_video_info.chip_id = pdev->device;
2509 pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2510 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2511 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2512 XGIvga_enabled = reg16 & 0x01;
2514 xgi_video_info.pcibus = pdev->bus->number;
2515 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2516 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2517 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2518 xgi_video_info.subsysdevice = pdev->subsystem_device;
2520 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2521 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2522 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2523 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2524 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2525 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2526 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2527 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2529 if (pci_enable_device(pdev)) {
2534 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2536 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2537 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2539 if (reg1 != 0xa1) { /*I/O error */
2540 printk("\nXGIfb: I/O error!!!");
2545 switch (xgi_video_info.chip_id) {
2546 case PCI_DEVICE_ID_XG_20:
2547 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2548 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2549 if (CR48&GPIOG_READ)
2550 xgi_video_info.chip = XG21;
2552 xgi_video_info.chip = XG20;
2553 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2555 case PCI_DEVICE_ID_XG_40:
2556 xgi_video_info.chip = XG40;
2557 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2559 case PCI_DEVICE_ID_XG_41:
2560 xgi_video_info.chip = XG41;
2561 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2563 case PCI_DEVICE_ID_XG_42:
2564 xgi_video_info.chip = XG42;
2565 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2567 case PCI_DEVICE_ID_XG_27:
2568 xgi_video_info.chip = XG27;
2569 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2576 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
2577 XGIhw_ext.jChipType = xgi_video_info.chip;
2579 switch (xgi_video_info.chip) {
2587 XGIhw_ext.bIntegratedMMEnabled = 1;
2593 XGIhw_ext.pDevice = NULL;
2594 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
2595 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
2596 if (XGIhw_ext.pjVirtualRomBase)
2597 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
2599 printk(KERN_INFO "XGIfb: Video ROM not found\n");
2601 XGIhw_ext.pjVirtualRomBase = NULL;
2602 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2604 XGIhw_ext.pjCustomizedROMImage = NULL;
2605 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2606 /* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
2607 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
2609 if (!XGIvga_enabled) {
2610 /* Mapping Max FB Size for 315 Init */
2611 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
2612 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2614 printk("XGIfb: XGIInit() ...");
2615 /* XGIInitNewt for LINUXBIOS only */
2616 if (XGIInitNew(&XGIhw_ext))
2622 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2628 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
2629 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2631 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2633 /* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
2634 /* Set SR13 ,14 temporarily for UDtech */
2635 outXGIIDXREG(XGISR, 0x13, 0x45);
2636 outXGIIDXREG(XGISR, 0x14, 0x51);
2641 if (XGIfb_get_dram_size()) {
2642 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
2647 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2648 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
2649 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
2650 /* Enable 2D accelerator engine */
2651 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
2654 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
2656 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
2657 printk("unable request memory size %x", xgi_video_info.video_size);
2658 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
2659 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
2664 if (!request_mem_region(xgi_video_info.mmio_base,
2665 xgi_video_info.mmio_size,
2667 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
2672 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
2673 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
2674 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
2675 xgi_video_info.mmio_size);
2677 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
2678 xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
2680 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
2681 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
2682 xgi_video_info.mmio_size / 1024);
2683 printk("XGIfb: XGIInitNew() ...");
2684 if (XGIInitNew(&XGIhw_ext))
2689 if (XGIfb_heap_init())
2690 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
2692 xgi_video_info.mtrr = (unsigned int) 0;
2694 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2695 xgi_video_info.hasVB = HASVB_NONE;
2696 if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
2697 xgi_video_info.hasVB = HASVB_NONE;
2698 } else if (xgi_video_info.chip == XG21) {
2699 inXGIIDXREG(XGICR, 0x38, CR38);
2700 if ((CR38&0xE0) == 0xC0) {
2701 xgi_video_info.disp_state = DISPTYPE_LCD;
2702 if (!XGIfb_GetXG21LVDSData()) {
2704 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
2705 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
2706 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
2707 XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
2711 } else if ((CR38&0xE0) == 0x60) {
2712 xgi_video_info.hasVB = HASVB_CHRONTEL;
2714 xgi_video_info.hasVB = HASVB_NONE;
2717 XGIfb_get_VB_type();
2720 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
2722 XGIhw_ext.ulExternalChip = 0;
2724 switch (xgi_video_info.hasVB) {
2726 inXGIIDXREG(XGIPART4, 0x01, reg);
2728 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2729 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2730 } else if (reg >= 0xD0) {
2731 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2732 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
2734 /* else if (reg >= 0xB0) {
2735 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
2736 inXGIIDXREG(XGIPART4, 0x23, reg1);
2737 printk("XGIfb: XGI301B bridge detected\n");
2740 XGIhw_ext.ujVBChipID = VB_CHIP_301;
2741 printk("XGIfb: XGI301 bridge detected\n");
2745 inXGIIDXREG(XGIPART4, 0x01, reg);
2747 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2748 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2749 } else if (reg >= 0xD0) {
2750 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2751 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2752 } else if (reg >= 0xB0) {
2753 inXGIIDXREG(XGIPART4, 0x23, reg1);
2755 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
2758 XGIhw_ext.ujVBChipID = VB_CHIP_302;
2759 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
2763 XGIhw_ext.ulExternalChip = 0x1;
2764 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
2766 case HASVB_TRUMPION:
2767 XGIhw_ext.ulExternalChip = 0x2;
2768 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
2770 case HASVB_CHRONTEL:
2771 XGIhw_ext.ulExternalChip = 0x4;
2772 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
2774 case HASVB_LVDS_CHRONTEL:
2775 XGIhw_ext.ulExternalChip = 0x5;
2776 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2779 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
2783 if (xgi_video_info.hasVB != HASVB_NONE)
2786 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2788 xgi_video_info.disp_state |= DISPMODE_SINGLE;
2790 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
2792 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
2795 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2797 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
2799 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
2803 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
2807 XGIfb_detectedpdc = 0;
2809 XGIfb_detectedlcda = 0xff;
2812 /* TW: Try to find about LCDA */
2814 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
2815 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2816 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
2818 inXGIIDXREG(XGICR, 0x34, tmp);
2820 /* Currently on LCDA? (Some BIOSes leave CR38) */
2821 inXGIIDXREG(XGICR, 0x38, tmp);
2822 if ((tmp & 0x03) == 0x03) {
2823 /* XGI_Pr.XGI_UseLCDA = 1; */
2825 /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
2826 inXGIIDXREG(XGICR, 0x35, tmp);
2828 /* XGI_Pr.XGI_UseLCDA = 1; */
2830 inXGIIDXREG(XGICR, 0x30, tmp);
2832 inXGIIDXREG(XGIPART1, 0x13, tmp);
2834 /* XGI_Pr.XGI_UseLCDA = 1; */
2845 if (xgifb_mode_idx >= 0)
2846 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
2848 if (xgifb_mode_idx < 0) {
2849 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2851 xgifb_mode_idx = DEFAULT_LCDMODE;
2852 if (xgi_video_info.chip == XG21)
2853 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
2856 xgifb_mode_idx = DEFAULT_TVMODE;
2859 xgifb_mode_idx = DEFAULT_MODE;
2864 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
2866 if (xgi_video_info.refresh_rate == 0)
2867 xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
2868 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
2869 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
2870 xgi_video_info.refresh_rate = 60;
2873 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
2874 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
2875 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
2876 xgi_video_info.org_x = xgi_video_info.org_y = 0;
2877 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
2878 switch (xgi_video_info.video_bpp) {
2880 xgi_video_info.DstColor = 0x0000;
2881 xgi_video_info.XGI310_AccelDepth = 0x00000000;
2882 xgi_video_info.video_cmap_len = 256;
2885 xgi_video_info.DstColor = 0x8000;
2886 xgi_video_info.XGI310_AccelDepth = 0x00010000;
2887 xgi_video_info.video_cmap_len = 16;
2890 xgi_video_info.DstColor = 0xC000;
2891 xgi_video_info.XGI310_AccelDepth = 0x00020000;
2892 xgi_video_info.video_cmap_len = 16;
2895 xgi_video_info.video_cmap_len = 16;
2896 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
2900 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
2901 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
2902 xgi_video_info.refresh_rate);
2904 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
2905 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
2906 default_var.bits_per_pixel = xgi_video_info.video_bpp;
2908 XGIfb_bpp_to_var(&default_var);
2910 default_var.pixclock = (u32) (1000000000 /
2911 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
2912 XGIfb_mode_no, XGIfb_rate_idx));
2914 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
2915 XGIfb_mode_no, XGIfb_rate_idx,
2916 &default_var.left_margin, &default_var.right_margin,
2917 &default_var.upper_margin, &default_var.lower_margin,
2918 &default_var.hsync_len, &default_var.vsync_len,
2919 &default_var.sync, &default_var.vmode)) {
2921 if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
2922 default_var.yres <<= 1;
2923 default_var.yres_virtual <<= 1;
2924 } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
2925 default_var.pixclock >>= 1;
2926 default_var.yres >>= 1;
2927 default_var.yres_virtual >>= 1;
2932 fb_info->flags = FBINFO_FLAG_DEFAULT;
2933 fb_info->var = default_var;
2934 fb_info->fix = XGIfb_fix;
2935 fb_info->par = &xgi_video_info;
2936 fb_info->screen_base = xgi_video_info.video_vbase;
2937 fb_info->fbops = &XGIfb_ops;
2938 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
2939 fb_info->pseudo_palette = pseudo_palette;
2941 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2944 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
2945 (unsigned int) xgi_video_info.video_size,
2946 MTRR_TYPE_WRCOMB, 1);
2947 if (xgi_video_info.mtrr)
2948 printk(KERN_INFO "XGIfb: Added MTRRs\n");
2951 if (register_framebuffer(fb_info) < 0) {
2956 XGIfb_registered = 1;
2958 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
2959 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
2968 iounmap(xgi_video_info.mmio_vbase);
2969 iounmap(xgi_video_info.video_vbase);
2970 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2972 release_mem_region(xgi_video_info.video_base,
2973 xgi_video_info.video_size);
2975 vfree(XGIhw_ext.pjVirtualRomBase);
2976 framebuffer_release(fb_info);
2980 /*****************************************************/
2981 /* PCI DEVICE HANDLING */
2982 /*****************************************************/
2984 static void __devexit xgifb_remove(struct pci_dev *pdev)
2986 unregister_framebuffer(fb_info);
2987 iounmap(xgi_video_info.mmio_vbase);
2988 iounmap(xgi_video_info.video_vbase);
2989 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2990 release_mem_region(xgi_video_info.video_base,
2991 xgi_video_info.video_size);
2992 vfree(XGIhw_ext.pjVirtualRomBase);
2993 framebuffer_release(fb_info);
2994 pci_set_drvdata(pdev, NULL);
2997 static struct pci_driver xgifb_driver = {
2999 .id_table = xgifb_pci_table,
3000 .probe = xgifb_probe,
3001 .remove = __devexit_p(xgifb_remove)
3004 XGIINITSTATIC int __init xgifb_init(void)
3006 char *option = NULL;
3008 if (fb_get_options("xgifb", &option))
3010 XGIfb_setup(option);
3012 return pci_register_driver(&xgifb_driver);
3016 module_init(xgifb_init);
3019 /*****************************************************/
3021 /*****************************************************/
3025 static char *mode = NULL;
3026 static int vesa = 0;
3027 static unsigned int rate = 0;
3028 static unsigned int mem = 0;
3029 static char *forcecrt2type = NULL;
3030 static int forcecrt1 = -1;
3031 static int pdc = -1;
3032 static int pdc1 = -1;
3033 static int noypan = -1;
3034 static int nomax = -1;
3035 static int userom = -1;
3036 static int useoem = -1;
3037 static char *tvstandard = NULL;
3038 static int nocrt2rate = 0;
3039 static int scalelcd = -1;
3040 static char *specialtiming = NULL;
3041 static int lvdshl = -1;
3042 static int tvxposoffset = 0, tvyposoffset = 0;
3043 #if !defined(__i386__) && !defined(__x86_64__)
3044 static int resetcard = 0;
3045 static int videoram = 0;
3048 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3049 MODULE_LICENSE("GPL");
3050 MODULE_AUTHOR("XGITECH , Others");
3052 module_param(mem, int, 0);
3053 module_param(noypan, int, 0);
3054 module_param(nomax, int, 0);
3055 module_param(userom, int, 0);
3056 module_param(useoem, int, 0);
3057 module_param(mode, charp, 0);
3058 module_param(vesa, int, 0);
3059 module_param(rate, int, 0);
3060 module_param(forcecrt1, int, 0);
3061 module_param(forcecrt2type, charp, 0);
3062 module_param(scalelcd, int, 0);
3063 module_param(pdc, int, 0);
3064 module_param(pdc1, int, 0);
3065 module_param(specialtiming, charp, 0);
3066 module_param(lvdshl, int, 0);
3067 module_param(tvstandard, charp, 0);
3068 module_param(tvxposoffset, int, 0);
3069 module_param(tvyposoffset, int, 0);
3070 module_param(filter, int, 0);
3071 module_param(nocrt2rate, int, 0);
3072 #if !defined(__i386__) && !defined(__x86_64__)
3073 module_param(resetcard, int, 0);
3074 module_param(videoram, int, 0);
3077 MODULE_PARM_DESC(mem,
3078 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3079 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3080 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3081 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3082 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3083 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3084 "for XFree86 4.x/X.org 6.7 and later.\n");
3086 MODULE_PARM_DESC(noypan,
3087 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3088 "will be performed by redrawing the screen. (default: 0)\n");
3090 MODULE_PARM_DESC(nomax,
3091 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3092 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3093 "this is set to anything other than 0, xgifb will not do this and thereby\n"
3094 "enable the user to positively specify a virtual Y size of the screen using\n"
3095 "fbset. (default: 0)\n");
3097 MODULE_PARM_DESC(mode,
3098 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3099 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3100 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3101 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3103 MODULE_PARM_DESC(vesa,
3104 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3105 "0x117 (default: 0x0103)\n");
3107 MODULE_PARM_DESC(rate,
3108 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3109 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3110 "will be ignored (default: 60)\n");
3112 MODULE_PARM_DESC(forcecrt1,
3113 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
3114 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3115 "0=CRT1 OFF) (default: [autodetected])\n");
3117 MODULE_PARM_DESC(forcecrt2type,
3118 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3119 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3120 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3121 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3122 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3123 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3124 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3125 "depends on the very hardware in use. (default: [autodetected])\n");
3127 MODULE_PARM_DESC(scalelcd,
3128 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3129 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3130 "show black bars around the image, TMDS panels will probably do the scaling\n"
3131 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3133 MODULE_PARM_DESC(pdc,
3134 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3135 "should detect this correctly in most cases; however, sometimes this is not\n"
3136 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3137 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3138 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3139 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3141 MODULE_PARM_DESC(pdc1,
3142 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3143 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3144 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3145 "implemented yet.\n");
3147 MODULE_PARM_DESC(specialtiming,
3148 "\nPlease refer to documentation for more information on this option.\n");
3150 MODULE_PARM_DESC(lvdshl,
3151 "\nPlease refer to documentation for more information on this option.\n");
3153 MODULE_PARM_DESC(tvstandard,
3154 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3155 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3157 MODULE_PARM_DESC(tvxposoffset,
3158 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3161 MODULE_PARM_DESC(tvyposoffset,
3162 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3165 MODULE_PARM_DESC(filter,
3166 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3167 "(Possible values 0-7, default: [no filter])\n");
3169 MODULE_PARM_DESC(nocrt2rate,
3170 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3171 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3173 static int __init xgifb_init_module(void)
3175 printk("\nXGIfb_init_module");
3177 XGIfb_search_mode(mode);
3178 else if (vesa != -1)
3179 XGIfb_search_vesamode(vesa);
3181 return xgifb_init();
3184 static void __exit xgifb_remove_module(void)
3186 pci_unregister_driver(&xgifb_driver);
3187 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3190 module_init(xgifb_init_module);
3191 module_exit(xgifb_remove_module);
3193 #endif /* /MODULE */
3195 EXPORT_SYMBOL(XGI_malloc);
3196 EXPORT_SYMBOL(XGI_free);