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 xgifb_reg_set(XGISR, 0x05, 0x86);
74 xgifb_reg_set(XGISR, 0x08, 0x4f);
75 xgifb_reg_set(XGISR, 0x0f, 0x20);
76 xgifb_reg_set(XGISR, 0x11, 0x4f);
77 xgifb_reg_set(XGISR, 0x13, 0x45);
78 xgifb_reg_set(XGISR, 0x14, 0x51);
79 xgifb_reg_set(XGISR, 0x1e, 0x41);
80 xgifb_reg_set(XGISR, 0x1f, 0x0);
81 xgifb_reg_set(XGISR, 0x20, 0xa1);
82 xgifb_reg_set(XGISR, 0x22, 0xfb);
83 xgifb_reg_set(XGISR, 0x26, 0x22);
84 xgifb_reg_set(XGISR, 0x3e, 0x07);
87 /* xgifb_reg_set(XGICR, 0x19, 0x00); */
88 /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
89 /* xgifb_reg_set(XGICR, 0x22, 0xff); */
90 /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
92 /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
94 /* xgifb_reg_set(XGICR, 0x57, 0x0); */
95 /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
97 /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
98 /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
100 xgifb_reg_set(XGICR, 0x99, 0x1);
101 xgifb_reg_set(XGICR, 0x41, 0x40);
104 for (i = 0; i < 0x4f; i++) {
105 reg = xgifb_reg_get(XGISR, i);
106 printk("\no 3c4 %x", i);
107 printk("\ni 3c5 => %x", reg);
110 for (i = 0; i < 0xF0; i++) {
111 reg = xgifb_reg_get(XGICR, i);
112 printk("\no 3d4 %x", i);
113 printk("\ni 3d5 => %x", reg);
116 xgifb_reg_set(XGIPART1,0x2F,1);
117 for (i=1; i < 0x50; i++) {
118 reg = xgifb_reg_get(XGIPART1, i);
119 printk("\no d004 %x", i);
120 printk("\ni d005 => %x", reg);
123 for (i=0; i < 0x50; i++) {
124 reg = xgifb_reg_get(XGIPART2, i);
125 printk("\no d010 %x", i);
126 printk("\ni d011 => %x", reg);
128 for (i=0; i < 0x50; i++) {
129 reg = xgifb_reg_get(XGIPART3, i);
130 printk("\no d012 %x",i);
131 printk("\ni d013 => %x",reg);
133 for (i=0; i < 0x50; i++) {
134 reg = xgifb_reg_get(XGIPART4, i);
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;
186 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
191 static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
192 struct xgi_hw_device_info *HwDeviceExtension,
193 unsigned char modeno, unsigned char rateindex,
194 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
195 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
198 unsigned short ModeNo = modeno;
199 unsigned short ModeIdIndex = 0, index = 0;
200 unsigned short RefreshRateTableIndex = 0;
202 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
203 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
204 unsigned char sr_data, cr_data, cr_data2;
205 unsigned long cr_data3;
206 int A, B, C, D, E, F, temp, j;
207 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
208 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
209 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
210 ModeIdIndex, XGI_Pr);
212 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
216 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
217 RefreshRateTableIndex += (rateindex - 1);
219 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
221 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
223 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
225 /* Horizontal total */
226 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
230 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
232 Horizontal display enable end
233 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
235 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
238 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
240 /* Horizontal retrace (=sync) start */
241 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
244 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
246 /* Horizontal blank start */
247 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
249 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
251 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
253 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
255 /* Horizontal blank end */
256 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
257 | ((unsigned short) (sr_data & 0x03) << 6);
259 /* Horizontal retrace (=sync) end */
260 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
262 temp = HBE - ((E - 1) & 255);
263 B = (temp > 0) ? temp : (temp + 256);
265 temp = HRE - ((E + F + 3) & 63);
266 C = (temp > 0) ? temp : (temp + 64);
270 *left_margin = D * 8;
271 *right_margin = F * 8;
274 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
276 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
278 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
281 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
282 | ((unsigned short) (cr_data2 & 0x20) << 4)
283 | ((unsigned short) (sr_data & 0x01) << 10);
286 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
288 /* Vertical display enable end */
290 VDE = (cr_data & 0xff) |
291 ((unsigned short) (cr_data2 & 0x02) << 7) |
292 ((unsigned short) (cr_data2 & 0x40) << 3) |
293 ((unsigned short) (sr_data & 0x02) << 9);
295 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
298 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
300 /* Vertical retrace (=sync) start */
301 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
302 | ((unsigned short) (cr_data2 & 0x80) << 2)
303 | ((unsigned short) (sr_data & 0x08) << 7);
306 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
308 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
310 /* Vertical blank start */
311 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
312 | ((unsigned short) (cr_data3 & 0x20) << 4)
313 | ((unsigned short) (sr_data & 0x04) << 8);
315 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
317 /* Vertical blank end */
318 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
319 temp = VBE - ((E - 1) & 511);
320 B = (temp > 0) ? temp : (temp + 512);
322 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
324 /* Vertical retrace (=sync) end */
325 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
326 temp = VRE - ((E + F - 1) & 31);
327 C = (temp > 0) ? temp : (temp + 32);
335 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
336 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
338 *sync |= FB_SYNC_VERT_HIGH_ACT;
340 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
341 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
343 *sync |= FB_SYNC_HOR_HIGH_ACT;
345 *vmode = FB_VMODE_NONINTERLACED;
346 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
347 *vmode = FB_VMODE_INTERLACED;
350 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
351 if (XGI_Pr->EModeIDTable[j].Ext_ModeID
352 == XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
353 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag
355 *vmode = FB_VMODE_DOUBLE;
366 static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
368 XGI_Pr->RelIO = BaseAddr;
369 XGI_Pr->P3c4 = BaseAddr + 0x14;
370 XGI_Pr->P3d4 = BaseAddr + 0x24;
371 XGI_Pr->P3c0 = BaseAddr + 0x10;
372 XGI_Pr->P3ce = BaseAddr + 0x1e;
373 XGI_Pr->P3c2 = BaseAddr + 0x12;
374 XGI_Pr->P3ca = BaseAddr + 0x1a;
375 XGI_Pr->P3c6 = BaseAddr + 0x16;
376 XGI_Pr->P3c7 = BaseAddr + 0x17;
377 XGI_Pr->P3c8 = BaseAddr + 0x18;
378 XGI_Pr->P3c9 = BaseAddr + 0x19;
379 XGI_Pr->P3da = BaseAddr + 0x2A;
380 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
381 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
382 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
383 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
384 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2; /* 301 palette address port registers */
388 void XGIfb_set_reg4(u16 port, unsigned long data)
390 outl((u32)(data & 0xffffffff), port);
393 u32 XGIfb_get_reg3(u16 port)
401 /* ------------ Interface for init & mode switching code ------------- */
403 unsigned char XGIfb_query_VGA_config_space(
404 struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
405 unsigned long set, unsigned long *value)
407 static struct pci_dev *pdev = NULL;
408 static unsigned char init = 0, valid_pdev = 0;
411 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
413 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
417 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
426 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
427 xgi_video_info.chip_id);
432 pci_read_config_dword(pdev, offset, (u32 *) value);
434 pci_write_config_dword(pdev, offset, (u32)(*value));
440 unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
441 unsigned long offset, unsigned long set, unsigned long *value)
443 static struct pci_dev *pdev = NULL;
444 static unsigned char init = 0, valid_pdev = 0;
449 switch (xgi_video_info.chip) {
451 nbridge_id = PCI_DEVICE_ID_XG_540;
454 nbridge_id = PCI_DEVICE_ID_XG_630;
457 nbridge_id = PCI_DEVICE_ID_XG_730;
460 nbridge_id = PCI_DEVICE_ID_XG_550;
463 nbridge_id = PCI_DEVICE_ID_XG_650;
466 nbridge_id = PCI_DEVICE_ID_XG_740;
473 pdev = pci_get_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
481 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
487 pci_read_config_dword(pdev, offset, (u32 *)value);
489 pci_write_config_dword(pdev, offset, (u32)(*value));
494 /* ------------------ Internal helper routines ----------------- */
496 static void XGIfb_search_mode(const char *name)
501 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
502 xgifb_mode_idx = DEFAULT_MODE;
503 if ((xgi_video_info.chip == XG21)
504 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
506 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
511 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
512 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
513 xgifb_mode_idx = DEFAULT_MODE;
514 if ((xgi_video_info.chip == XG21)
515 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
517 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
522 while (XGIbios_mode[i].mode_no != 0) {
523 l = min(strlen(name), strlen(XGIbios_mode[i].name));
524 if (!strncmp(name, XGIbios_mode[i].name, l)) {
532 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
535 static void XGIfb_search_vesamode(unsigned int vesamode)
541 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
542 xgifb_mode_idx = DEFAULT_MODE;
543 if ((xgi_video_info.chip == XG21)
544 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
546 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
551 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
553 while (XGIbios_mode[i].mode_no != 0) {
554 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode)
555 || (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
563 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
566 static int XGIfb_GetXG21LVDSData(void)
569 unsigned char *pData;
572 tmp = xgifb_reg_get(XGISR, 0x1e);
573 xgifb_reg_set(XGISR, 0x1e, tmp | 4);
575 pData = xgi_video_info.mmio_vbase + 0x20000;
576 if ((pData[0x0] == 0x55) && (pData[0x1] == 0xAA) && (pData[0x65] & 0x1)) {
577 i = pData[0x316] | (pData[0x317] << 8);
584 XGI21_LCDCapList[k].LVDS_Capability = pData[i]
585 | (pData[i + 1] << 8);
586 XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
588 XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
590 XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
592 XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
594 XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
596 XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
598 XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
599 | (pData[i + 15] << 8);
600 XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
601 | (pData[i + 17] << 8);
602 XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
603 XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
604 XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
605 XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
606 XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
607 XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
608 XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
612 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
613 / sizeof(struct XGI21_LVDSCapStruct))));
619 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
623 int XGIfb_mode_idx = 0;
626 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
627 && (XGIbios_mode[XGIfb_mode_idx].xres
628 <= XGI21_LCDCapList[0].LVDSHDE)) {
629 if ((XGIbios_mode[XGIfb_mode_idx].xres
630 == XGI21_LCDCapList[0].LVDSHDE)
631 && (XGIbios_mode[XGIfb_mode_idx].yres
632 == XGI21_LCDCapList[0].LVDSVDE)
633 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
634 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
643 return XGIfb_mode_idx;
646 static int XGIfb_validate_mode(int myindex)
650 if (xgi_video_info.chip == XG21) {
651 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
653 xres = XGI21_LCDCapList[0].LVDSHDE;
654 yres = XGI21_LCDCapList[0].LVDSVDE;
655 if (XGIbios_mode[myindex].xres > xres)
657 if (XGIbios_mode[myindex].yres > yres)
659 if ((XGIbios_mode[myindex].xres < xres)
660 && (XGIbios_mode[myindex].yres < yres)) {
661 if (XGIbios_mode[myindex].bpp > 8)
670 /* FIXME: for now, all is valid on XG27 */
671 if (xgi_video_info.chip == XG27)
674 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
677 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
679 switch (XGIhw_ext.ulCRT2LCDType) {
720 /* case LCD_320x480: */ /* TW: FSTN */
731 if (XGIbios_mode[myindex].xres > xres)
733 if (XGIbios_mode[myindex].yres > yres)
735 if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
736 (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
737 switch (XGIbios_mode[myindex].xres) {
739 if (XGIbios_mode[myindex].yres != 512)
741 if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
745 if ((XGIbios_mode[myindex].yres != 400)
746 && (XGIbios_mode[myindex].yres
751 if (XGIbios_mode[myindex].yres != 600)
755 if ((XGIbios_mode[myindex].yres != 600)
756 && (XGIbios_mode[myindex].yres
759 if ((XGIbios_mode[myindex].yres == 600)
760 && (XGIhw_ext.ulCRT2LCDType
765 if ((XGIbios_mode[myindex].yres) != 768)
767 if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
771 if ((XGIbios_mode[myindex].yres != 768)
772 && (XGIbios_mode[myindex].yres
775 if ((XGIbios_mode[myindex].yres == 768)
776 && (XGIhw_ext.ulCRT2LCDType
781 if (XGIbios_mode[myindex].yres != 1050)
785 if (XGIbios_mode[myindex].yres != 1200)
792 switch (XGIbios_mode[myindex].xres) {
794 if (XGIbios_mode[myindex].yres != 512)
798 if ((XGIbios_mode[myindex].yres != 400)
799 && (XGIbios_mode[myindex].yres
804 if (XGIbios_mode[myindex].yres != 600)
808 if (XGIbios_mode[myindex].yres != 768)
812 if ((XGIbios_mode[myindex].yres != 960)
813 && (XGIbios_mode[myindex].yres
816 if (XGIbios_mode[myindex].yres == 960) {
817 if (XGIhw_ext.ulCRT2LCDType
823 if (XGIbios_mode[myindex].yres != 1050)
827 if (XGIbios_mode[myindex].yres != 1200)
836 switch (XGIbios_mode[myindex].xres) {
842 if (xgi_video_info.TV_type == TVMODE_NTSC) {
843 if (XGIbios_mode[myindex].yres != 480)
845 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
846 if (XGIbios_mode[myindex].yres != 576)
849 /* TW: LVDS/CHRONTEL does not support 720 */
850 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
851 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
856 if (xgi_video_info.TV_type == TVMODE_NTSC) {
857 if (XGIbios_mode[myindex].bpp == 32)
866 if (XGIbios_mode[myindex].xres > 1280)
874 static void XGIfb_search_crt2type(const char *name)
881 while (XGI_crt2type[i].type_no != -1) {
882 if (!strcmp(name, XGI_crt2type[i].name)) {
883 XGIfb_crt2type = XGI_crt2type[i].type_no;
884 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
889 if (XGIfb_crt2type < 0)
890 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
893 static u8 XGIfb_search_refresh_rate(unsigned int rate)
898 xres = XGIbios_mode[xgifb_mode_idx].xres;
899 yres = XGIbios_mode[xgifb_mode_idx].yres;
902 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
903 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres
905 if (XGIfb_vrate[i].refresh == rate) {
906 XGIfb_rate_idx = XGIfb_vrate[i].idx;
908 } else if (XGIfb_vrate[i].refresh > rate) {
909 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
910 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
911 rate, XGIfb_vrate[i].refresh);
912 XGIfb_rate_idx = XGIfb_vrate[i].idx;
913 xgi_video_info.refresh_rate
914 = XGIfb_vrate[i].refresh;
915 } else if (((rate - XGIfb_vrate[i - 1].refresh)
916 <= 2) && (XGIfb_vrate[i].idx
918 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
919 rate, XGIfb_vrate[i-1].refresh);
920 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
921 xgi_video_info.refresh_rate
922 = XGIfb_vrate[i - 1].refresh;
925 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
926 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
927 rate, XGIfb_vrate[i].refresh);
928 XGIfb_rate_idx = XGIfb_vrate[i].idx;
934 if (XGIfb_rate_idx > 0) {
935 return XGIfb_rate_idx;
938 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
943 static void XGIfb_search_tvstd(const char *name)
950 while (XGI_tvtype[i].type_no != -1) {
951 if (!strcmp(name, XGI_tvtype[i].name)) {
952 XGIfb_tvmode = XGI_tvtype[i].type_no;
959 /* ----------- FBDev related routines for all series ----------- */
961 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
963 switch (var->bits_per_pixel) {
965 var->red.offset = var->green.offset = var->blue.offset = 0;
966 var->red.length = var->green.length = var->blue.length = 6;
967 xgi_video_info.video_cmap_len = 256;
970 var->red.offset = 11;
972 var->green.offset = 5;
973 var->green.length = 6;
974 var->blue.offset = 0;
975 var->blue.length = 5;
976 var->transp.offset = 0;
977 var->transp.length = 0;
978 xgi_video_info.video_cmap_len = 16;
981 var->red.offset = 16;
983 var->green.offset = 8;
984 var->green.length = 8;
985 var->blue.offset = 0;
986 var->blue.length = 8;
987 var->transp.offset = 24;
988 var->transp.length = 8;
989 xgi_video_info.video_cmap_len = 16;
994 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
995 struct fb_info *info)
998 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1000 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1002 #if defined(__powerpc__)
1003 u8 sr_data, cr_data;
1005 unsigned int drate = 0, hrate = 0;
1008 /* unsigned char reg, reg1; */
1010 DEBUGPRN("Inside do_set_var");
1011 /* 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); */
1013 info->var.xres_virtual = var->xres_virtual;
1014 info->var.yres_virtual = var->yres_virtual;
1015 info->var.bits_per_pixel = var->bits_per_pixel;
1017 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1019 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1021 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1023 /* var->yres <<= 1; */
1026 if (!htotal || !vtotal) {
1027 DPRINTK("XGIfb: Invalid 'var' information\n");
1029 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1030 var->pixclock, htotal, vtotal);
1032 if (var->pixclock && htotal && vtotal) {
1033 drate = 1000000000 / var->pixclock;
1034 hrate = (drate * 1000) / htotal;
1035 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1038 xgi_video_info.refresh_rate = 60;
1041 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1042 var->xres, var->yres, var->bits_per_pixel, xgi_video_info.refresh_rate);
1044 old_mode = xgifb_mode_idx;
1047 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1048 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1049 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1050 && (XGIbios_mode[xgifb_mode_idx].yres
1052 && (XGIbios_mode[xgifb_mode_idx].bpp
1053 == var->bits_per_pixel)) {
1054 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1062 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1064 xgifb_mode_idx = -1;
1066 if (xgifb_mode_idx < 0) {
1067 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1068 var->yres, var->bits_per_pixel);
1069 xgifb_mode_idx = old_mode;
1073 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1074 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1075 xgi_video_info.refresh_rate = 60;
1080 XGIfb_pre_setmode();
1081 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1082 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1085 info->fix.line_length = ((info->var.xres_virtual
1086 * info->var.bits_per_pixel) >> 6);
1088 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1090 xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1091 xgifb_reg_set(XGISR, 0x0E, (info->fix.line_length & 0xff00) >> 8);
1093 XGIfb_post_setmode();
1095 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1096 XGIbios_mode[xgifb_mode_idx].xres,
1097 XGIbios_mode[xgifb_mode_idx].yres,
1098 XGIbios_mode[xgifb_mode_idx].bpp,
1099 xgi_video_info.refresh_rate);
1101 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1102 xgi_video_info.video_vwidth = info->var.xres_virtual;
1103 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1104 xgi_video_info.video_vheight = info->var.yres_virtual;
1105 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1106 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1107 xgi_video_info.video_linelength = info->var.xres_virtual
1108 * (xgi_video_info.video_bpp >> 3);
1109 switch (xgi_video_info.video_bpp) {
1111 xgi_video_info.DstColor = 0x0000;
1112 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1113 xgi_video_info.video_cmap_len = 256;
1114 #if defined(__powerpc__)
1115 cr_data = xgifb_reg_get(XGICR, 0x4D);
1116 xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
1120 xgi_video_info.DstColor = 0x8000;
1121 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1122 #if defined(__powerpc__)
1123 cr_data = xgifb_reg_get(XGICR, 0x4D);
1124 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1126 xgi_video_info.video_cmap_len = 16;
1129 xgi_video_info.DstColor = 0xC000;
1130 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1131 xgi_video_info.video_cmap_len = 16;
1132 #if defined(__powerpc__)
1133 cr_data = xgifb_reg_get(XGICR, 0x4D);
1134 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1138 xgi_video_info.video_cmap_len = 16;
1139 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1143 XGIfb_bpp_to_var(var); /*update ARGB info*/
1144 DEBUGPRN("End of do_set_var");
1151 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1155 /* printk("Inside pan_var"); */
1157 if (var->xoffset > (var->xres_virtual - var->xres)) {
1158 /* printk("Pan: xo: %d xv %d xr %d\n",
1159 var->xoffset, var->xres_virtual, var->xres); */
1162 if (var->yoffset > (var->yres_virtual - var->yres)) {
1163 /* printk("Pan: yo: %d yv %d yr %d\n",
1164 var->yoffset, var->yres_virtual, var->yres); */
1167 base = var->yoffset * var->xres_virtual + var->xoffset;
1169 /* calculate base bpp dep. */
1170 switch (var->bits_per_pixel) {
1182 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1184 xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1185 xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1186 xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1187 xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
1188 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1190 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1191 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1192 xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1193 xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1194 xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1195 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1197 /* printk("End of pan_var"); */
1202 static int XGIfb_open(struct fb_info *info, int user)
1207 static int XGIfb_release(struct fb_info *info, int user)
1212 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1216 switch (var->bits_per_pixel) {
1230 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1231 unsigned blue, unsigned transp, struct fb_info *info)
1233 if (regno >= XGIfb_get_cmap_len(&info->var))
1236 switch (info->var.bits_per_pixel) {
1238 outb(regno, XGIDACA);
1239 outb((red >> 10), XGIDACD);
1240 outb((green >> 10), XGIDACD);
1241 outb((blue >> 10), XGIDACD);
1242 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1243 outb(regno, XGIDAC2A);
1244 outb((red >> 8), XGIDAC2D);
1245 outb((green >> 8), XGIDAC2D);
1246 outb((blue >> 8), XGIDAC2D);
1250 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1251 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1258 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1265 static int XGIfb_set_par(struct fb_info *info)
1269 /* printk("XGIfb: inside set_par\n"); */
1270 err = XGIfb_do_set_var(&info->var, 1, info);
1273 XGIfb_get_fix(&info->fix, -1, info);
1274 /* printk("XGIfb: end of set_par\n"); */
1278 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1280 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1282 unsigned int vtotal = 0;
1283 unsigned int drate = 0, hrate = 0;
1285 int refresh_rate, search_idx;
1287 DEBUGPRN("Inside check_var");
1289 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1290 vtotal = var->upper_margin + var->yres + var->lower_margin
1293 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1294 vtotal = var->upper_margin + var->yres + var->lower_margin
1297 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1298 vtotal = var->upper_margin + (var->yres / 2)
1299 + var->lower_margin + var->vsync_len;
1301 vtotal = var->upper_margin + var->yres + var->lower_margin
1304 if (!(htotal) || !(vtotal))
1305 XGIFAIL("XGIfb: no valid timing data");
1307 if (var->pixclock && htotal && vtotal) {
1308 drate = 1000000000 / var->pixclock;
1309 hrate = (drate * 1000) / htotal;
1310 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1312 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1313 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1314 __func__, var->pixclock, htotal, vtotal,
1315 __func__, drate, hrate, xgi_video_info.refresh_rate);
1317 xgi_video_info.refresh_rate = 60;
1321 if ((var->pixclock) && (htotal)) {
1322 drate = 1E12 / var->pixclock;
1323 hrate = drate / htotal;
1324 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1329 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1330 if ((var->xres == 1024) && (var->yres == 600))
1334 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1335 (XGIbios_mode[search_idx].xres <= var->xres)) {
1336 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1337 (XGIbios_mode[search_idx].yres == var->yres) &&
1338 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1339 if (XGIfb_validate_mode(search_idx) > 0) {
1349 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1350 var->xres, var->yres, var->bits_per_pixel);
1352 while (XGIbios_mode[search_idx].mode_no != 0) {
1354 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1355 (var->yres <= XGIbios_mode[search_idx].yres) &&
1356 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1357 if (XGIfb_validate_mode(search_idx) > 0) {
1365 var->xres = XGIbios_mode[search_idx].xres;
1366 var->yres = XGIbios_mode[search_idx].yres;
1367 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1368 var->xres, var->yres, var->bits_per_pixel);
1371 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1372 var->xres, var->yres, var->bits_per_pixel);
1377 /* TW: TODO: Check the refresh rate */
1379 /* Adapt RGB settings */
1380 XGIfb_bpp_to_var(var);
1382 /* Sanity check for offsets */
1383 if (var->xoffset < 0)
1385 if (var->yoffset < 0)
1389 if (var->xres != var->xres_virtual)
1390 var->xres_virtual = var->xres;
1391 if (var->yres != var->yres_virtual)
1392 var->yres_virtual = var->yres;
1394 /* TW: Now patch yres_virtual if we use panning */
1395 /* May I do this? */
1396 /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1397 /* if (var->yres_virtual <= var->yres) { */
1398 /* TW: Paranoia check */
1399 /* var->yres_virtual = var->yres; */
1403 /* Truncate offsets to maximum if too high */
1404 if (var->xoffset > var->xres_virtual - var->xres)
1405 var->xoffset = var->xres_virtual - var->xres - 1;
1407 if (var->yoffset > var->yres_virtual - var->yres)
1408 var->yoffset = var->yres_virtual - var->yres - 1;
1410 /* Set everything else to 0 */
1411 var->red.msb_right =
1412 var->green.msb_right =
1413 var->blue.msb_right =
1414 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1416 DEBUGPRN("end of check_var");
1421 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1422 struct fb_info *info)
1426 /* printk("\nInside pan_display:\n"); */
1428 if (var->xoffset > (var->xres_virtual - var->xres))
1430 if (var->yoffset > (var->yres_virtual - var->yres))
1433 if (var->vmode & FB_VMODE_YWRAP) {
1434 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1438 if (var->xoffset + info->var.xres > info->var.xres_virtual
1439 || var->yoffset + info->var.yres
1440 > info->var.yres_virtual)
1443 err = XGIfb_pan_var(var);
1447 info->var.xoffset = var->xoffset;
1448 info->var.yoffset = var->yoffset;
1449 if (var->vmode & FB_VMODE_YWRAP)
1450 info->var.vmode |= FB_VMODE_YWRAP;
1452 info->var.vmode &= ~FB_VMODE_YWRAP;
1454 /* printk("End of pan_display\n"); */
1459 static int XGIfb_blank(int blank, struct fb_info *info)
1463 reg = xgifb_reg_get(XGICR, 0x17);
1470 xgifb_reg_set(XGICR, 0x17, reg);
1471 xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1472 xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
1476 /* ----------- FBDev related routines for all series ---------- */
1478 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1479 struct fb_info *info)
1481 DEBUGPRN("inside get_fix");
1482 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1484 strcpy(fix->id, myid);
1486 fix->smem_start = xgi_video_info.video_base;
1488 fix->smem_len = xgi_video_info.video_size;
1490 fix->type = video_type;
1492 if (xgi_video_info.video_bpp == 8)
1493 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1495 fix->visual = FB_VISUAL_DIRECTCOLOR;
1502 fix->line_length = xgi_video_info.video_linelength;
1503 fix->mmio_start = xgi_video_info.mmio_base;
1504 fix->mmio_len = xgi_video_info.mmio_size;
1505 fix->accel = FB_ACCEL_XGI_XABRE;
1507 DEBUGPRN("end of get_fix");
1511 static struct fb_ops XGIfb_ops = {
1512 .owner = THIS_MODULE,
1513 .fb_open = XGIfb_open,
1514 .fb_release = XGIfb_release,
1515 .fb_check_var = XGIfb_check_var,
1516 .fb_set_par = XGIfb_set_par,
1517 .fb_setcolreg = XGIfb_setcolreg,
1519 .fb_pan_display = XGIfb_pan_display,
1521 .fb_blank = XGIfb_blank,
1522 .fb_fillrect = cfb_fillrect,
1523 .fb_copyarea = cfb_copyarea,
1524 .fb_imageblit = cfb_imageblit,
1525 /* .fb_mmap = XGIfb_mmap, */
1528 /* ---------------- Chip generation dependent routines ---------------- */
1530 /* for XGI 315/550/650/740/330 */
1532 static int XGIfb_get_dram_size(void)
1538 /* xorg driver sets 32MB * 1 channel */
1539 if (xgi_video_info.chip == XG27)
1540 xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1542 reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE);
1543 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1544 case XGI_DRAM_SIZE_1MB:
1545 xgi_video_info.video_size = 0x100000;
1547 case XGI_DRAM_SIZE_2MB:
1548 xgi_video_info.video_size = 0x200000;
1550 case XGI_DRAM_SIZE_4MB:
1551 xgi_video_info.video_size = 0x400000;
1553 case XGI_DRAM_SIZE_8MB:
1554 xgi_video_info.video_size = 0x800000;
1556 case XGI_DRAM_SIZE_16MB:
1557 xgi_video_info.video_size = 0x1000000;
1559 case XGI_DRAM_SIZE_32MB:
1560 xgi_video_info.video_size = 0x2000000;
1562 case XGI_DRAM_SIZE_64MB:
1563 xgi_video_info.video_size = 0x4000000;
1565 case XGI_DRAM_SIZE_128MB:
1566 xgi_video_info.video_size = 0x8000000;
1568 case XGI_DRAM_SIZE_256MB:
1569 xgi_video_info.video_size = 0x10000000;
1575 tmp = (reg & 0x0c) >> 2;
1576 switch (xgi_video_info.chip) {
1612 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1613 /* PLiad fixed for benchmarking and fb set */
1614 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1615 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1617 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1618 xgi_video_info.video_size, ChannelNum);
1623 static void XGIfb_detect_VB(void)
1627 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1629 switch (xgi_video_info.hasVB) {
1630 case HASVB_LVDS_CHRONTEL:
1631 case HASVB_CHRONTEL:
1635 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1639 cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
1641 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1650 if (XGIfb_crt2type != -1)
1651 /* TW: Override with option */
1652 xgi_video_info.disp_state = XGIfb_crt2type;
1653 else if (cr32 & XGI_VB_TV)
1654 xgi_video_info.disp_state = DISPTYPE_TV;
1655 else if (cr32 & XGI_VB_LCD)
1656 xgi_video_info.disp_state = DISPTYPE_LCD;
1657 else if (cr32 & XGI_VB_CRT2)
1658 xgi_video_info.disp_state = DISPTYPE_CRT2;
1660 xgi_video_info.disp_state = 0;
1662 if (XGIfb_tvplug != -1)
1663 /* PR/TW: Override with option */
1664 xgi_video_info.TV_plug = XGIfb_tvplug;
1665 else if (cr32 & XGI_VB_HIVISION) {
1666 xgi_video_info.TV_type = TVMODE_HIVISION;
1667 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1668 } else if (cr32 & XGI_VB_SVIDEO)
1669 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1670 else if (cr32 & XGI_VB_COMPOSITE)
1671 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1672 else if (cr32 & XGI_VB_SCART)
1673 xgi_video_info.TV_plug = TVPLUG_SCART;
1675 if (xgi_video_info.TV_type == 0) {
1676 temp = xgifb_reg_get(XGICR, 0x38);
1678 xgi_video_info.TV_type = TVMODE_PAL;
1680 xgi_video_info.TV_type = TVMODE_NTSC;
1683 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1684 if (XGIfb_forcecrt1 != -1) {
1685 if (XGIfb_forcecrt1)
1692 static void XGIfb_get_VB_type(void)
1696 if (!XGIfb_has_VB()) {
1697 reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
1698 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1699 case XGI310_EXTERNAL_CHIP_LVDS:
1700 xgi_video_info.hasVB = HASVB_LVDS;
1702 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1703 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1711 static int XGIfb_has_VB(void)
1715 vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
1716 switch (vb_chipid) {
1718 xgi_video_info.hasVB = HASVB_301;
1721 xgi_video_info.hasVB = HASVB_302;
1724 xgi_video_info.hasVB = HASVB_NONE;
1730 /* ------------------ Sensing routines ------------------ */
1732 /* TW: Determine and detect attached devices on XGI30x */
1733 int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1737 xgifb_reg_set(XGIPART4, 0x11, tempbl);
1738 temp = tempbh | tempcl;
1739 setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1740 for (i = 0; i < 10; i++)
1741 XGI_LongWait(&XGI_Pr);
1743 temp = xgifb_reg_get(XGIPART4, 0x03);
1749 void XGI_Sense30x(void)
1752 u8 testsvhs_tempbl, testsvhs_tempbh;
1753 u8 testsvhs_tempcl, testsvhs_tempch;
1754 u8 testcvbs_tempbl, testcvbs_tempbh;
1755 u8 testcvbs_tempcl, testcvbs_tempch;
1756 u8 testvga2_tempbl, testvga2_tempbh;
1757 u8 testvga2_tempcl, testvga2_tempch;
1760 backupP4_0d = xgifb_reg_get(XGIPART4, 0x0d);
1761 xgifb_reg_set(XGIPART4, 0x0d, (backupP4_0d | 0x04));
1763 testvga2_tempbh = 0x00;
1764 testvga2_tempbl = 0xd1;
1765 testsvhs_tempbh = 0x00;
1766 testsvhs_tempbl = 0xb9;
1767 testcvbs_tempbh = 0x00;
1768 testcvbs_tempbl = 0xb3;
1769 if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
1771 testvga2_tempbh = 0x01;
1772 testvga2_tempbl = 0x90;
1773 testsvhs_tempbh = 0x01;
1774 testsvhs_tempbl = 0x6b;
1775 testcvbs_tempbh = 0x01;
1776 testcvbs_tempbl = 0x74;
1777 if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
1778 || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
1779 testvga2_tempbh = 0x00;
1780 testvga2_tempbl = 0x00;
1781 testsvhs_tempbh = 0x02;
1782 testsvhs_tempbl = 0x00;
1783 testcvbs_tempbh = 0x01;
1784 testcvbs_tempbl = 0x00;
1787 if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
1789 myflag = xgifb_reg_get(XGIPART4, 0x01);
1790 if (myflag & 0x04) {
1791 testvga2_tempbh = 0x00;
1792 testvga2_tempbl = 0xfd;
1793 testsvhs_tempbh = 0x00;
1794 testsvhs_tempbl = 0xdd;
1795 testcvbs_tempbh = 0x00;
1796 testcvbs_tempbl = 0xee;
1799 if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
1800 == VB_CHIP_302LV)) {
1801 testvga2_tempbh = 0x00;
1802 testvga2_tempbl = 0x00;
1803 testvga2_tempch = 0x00;
1804 testvga2_tempcl = 0x00;
1805 testsvhs_tempch = 0x04;
1806 testsvhs_tempcl = 0x08;
1807 testcvbs_tempch = 0x08;
1808 testcvbs_tempcl = 0x08;
1810 testvga2_tempch = 0x0e;
1811 testvga2_tempcl = 0x08;
1812 testsvhs_tempch = 0x06;
1813 testsvhs_tempcl = 0x04;
1814 testcvbs_tempch = 0x08;
1815 testcvbs_tempcl = 0x04;
1818 if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
1819 || testvga2_tempbl) {
1820 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
1821 testvga2_tempcl, testvga2_tempch);
1823 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
1824 orXGIIDXREG(XGICR, 0x32, 0x10);
1828 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
1831 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
1832 /* TW: So we can be sure that there IS a SVHS output */
1833 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1834 orXGIIDXREG(XGICR, 0x32, 0x02);
1838 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
1839 testcvbs_tempcl, testcvbs_tempch);
1841 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
1842 /* TW: So we can be sure that there IS a CVBS output */
1843 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1844 orXGIIDXREG(XGICR, 0x32, 0x01);
1847 XGIDoSense(0, 0, 0, 0);
1849 xgifb_reg_set(XGIPART4, 0x0d, backupP4_0d);
1852 /* --------------------- SetMode routines ------------------------- */
1854 static void XGIfb_pre_setmode(void)
1856 u8 cr30 = 0, cr31 = 0;
1858 cr31 = xgifb_reg_get(XGICR, 0x31);
1861 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1863 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
1864 cr31 |= XGI_DRIVER_MODE;
1867 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
1868 cr31 |= XGI_DRIVER_MODE;
1871 if (xgi_video_info.TV_type == TVMODE_HIVISION)
1872 cr30 = (XGI_VB_OUTPUT_HIVISION
1873 | XGI_SIMULTANEOUS_VIEW_ENABLE);
1874 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
1875 cr30 = (XGI_VB_OUTPUT_SVIDEO
1876 | XGI_SIMULTANEOUS_VIEW_ENABLE);
1877 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
1878 cr30 = (XGI_VB_OUTPUT_COMPOSITE
1879 | XGI_SIMULTANEOUS_VIEW_ENABLE);
1880 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
1881 cr30 = (XGI_VB_OUTPUT_SCART
1882 | XGI_SIMULTANEOUS_VIEW_ENABLE);
1883 cr31 |= XGI_DRIVER_MODE;
1885 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
1890 default: /* disable CRT2 */
1892 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
1895 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
1896 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
1897 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
1900 static void XGIfb_post_setmode(void)
1903 unsigned char doit = 1;
1905 xgifb_reg_set(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1906 xgifb_reg_set(XGICR, 0x13, 0x00);
1907 setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
1910 if (xgi_video_info.video_bpp == 8) {
1911 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
1912 if ((xgi_video_info.hasVB == HASVB_LVDS)
1913 || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
1916 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
1917 if (xgi_video_info.disp_state & DISPTYPE_LCD)
1921 /* TW: We can't switch off CRT1 if bridge is in slave mode */
1922 if (xgi_video_info.hasVB != HASVB_NONE) {
1923 reg = xgifb_reg_get(XGIPART1, 0x00);
1925 if ((reg & 0x50) == 0x10)
1932 reg = xgifb_reg_get(XGICR, 0x17);
1933 if ((XGIfb_crt1off) && (doit))
1937 xgifb_reg_set(XGICR, 0x17, reg);
1939 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
1941 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
1944 reg = xgifb_reg_get(XGIPART4, 0x01);
1946 if (reg < 0xB0) { /* Set filter for XGI301 */
1948 switch (xgi_video_info.video_width) {
1950 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
1953 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
1956 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
1959 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
1966 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1968 if (xgi_video_info.TV_type == TVMODE_NTSC) {
1970 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
1972 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
1974 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
1976 } else if (xgi_video_info.TV_plug
1977 == TVPLUG_COMPOSITE) {
1979 orXGIIDXREG(XGIPART2, 0x30, 0x20);
1981 switch (xgi_video_info.video_width) {
1983 xgifb_reg_set(XGIPART2, 0x35, 0xEB);
1984 xgifb_reg_set(XGIPART2, 0x36, 0x04);
1985 xgifb_reg_set(XGIPART2, 0x37, 0x25);
1986 xgifb_reg_set(XGIPART2, 0x38, 0x18);
1989 xgifb_reg_set(XGIPART2, 0x35, 0xEE);
1990 xgifb_reg_set(XGIPART2, 0x36, 0x0C);
1991 xgifb_reg_set(XGIPART2, 0x37, 0x22);
1992 xgifb_reg_set(XGIPART2, 0x38, 0x08);
1995 xgifb_reg_set(XGIPART2, 0x35, 0xEB);
1996 xgifb_reg_set(XGIPART2, 0x36, 0x15);
1997 xgifb_reg_set(XGIPART2, 0x37, 0x25);
1998 xgifb_reg_set(XGIPART2, 0x38, 0xF6);
2003 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2005 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2007 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2009 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2011 } else if (xgi_video_info.TV_plug
2012 == TVPLUG_COMPOSITE) {
2014 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2016 switch (xgi_video_info.video_width) {
2018 xgifb_reg_set(XGIPART2, 0x35, 0xF1);
2019 xgifb_reg_set(XGIPART2, 0x36, 0xF7);
2020 xgifb_reg_set(XGIPART2, 0x37, 0x1F);
2021 xgifb_reg_set(XGIPART2, 0x38, 0x32);
2024 xgifb_reg_set(XGIPART2, 0x35, 0xF3);
2025 xgifb_reg_set(XGIPART2, 0x36, 0x00);
2026 xgifb_reg_set(XGIPART2, 0x37, 0x1D);
2027 xgifb_reg_set(XGIPART2, 0x38, 0x20);
2030 xgifb_reg_set(XGIPART2, 0x35, 0xFC);
2031 xgifb_reg_set(XGIPART2, 0x36, 0xFB);
2032 xgifb_reg_set(XGIPART2, 0x37, 0x14);
2033 xgifb_reg_set(XGIPART2, 0x38, 0x2A);
2039 if ((filter >= 0) && (filter <= 7)) {
2040 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2041 XGI_TV_filter[filter_tb].filter[filter][0],
2042 XGI_TV_filter[filter_tb].filter[filter][1],
2043 XGI_TV_filter[filter_tb].filter[filter][2],
2044 XGI_TV_filter[filter_tb].filter[filter][3]
2049 (XGI_TV_filter[filter_tb].filter[filter][0]));
2053 (XGI_TV_filter[filter_tb].filter[filter][1]));
2057 (XGI_TV_filter[filter_tb].filter[filter][2]));
2061 (XGI_TV_filter[filter_tb].filter[filter][3]));
2070 XGIINITSTATIC int __init XGIfb_setup(char *options)
2074 xgi_video_info.refresh_rate = 0;
2076 printk(KERN_INFO "XGIfb: Options %s\n", options);
2078 if (!options || !*options)
2081 while ((this_opt = strsep(&options, ",")) != NULL) {
2086 if (!strncmp(this_opt, "mode:", 5)) {
2087 XGIfb_search_mode(this_opt + 5);
2088 } else if (!strncmp(this_opt, "vesa:", 5)) {
2089 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2090 } else if (!strncmp(this_opt, "mode:", 5)) {
2091 XGIfb_search_mode(this_opt + 5);
2092 } else if (!strncmp(this_opt, "vesa:", 5)) {
2093 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2094 } else if (!strncmp(this_opt, "vrate:", 6)) {
2095 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2096 } else if (!strncmp(this_opt, "rate:", 5)) {
2097 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2098 } else if (!strncmp(this_opt, "off", 3)) {
2100 } else if (!strncmp(this_opt, "crt1off", 7)) {
2102 } else if (!strncmp(this_opt, "filter:", 7)) {
2103 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2104 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2105 XGIfb_search_crt2type(this_opt + 14);
2106 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2107 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2108 } else if (!strncmp(this_opt, "tvmode:", 7)) {
2109 XGIfb_search_tvstd(this_opt + 7);
2110 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2111 XGIfb_search_tvstd(this_opt + 7);
2112 } else if (!strncmp(this_opt, "dstn", 4)) {
2114 /* TW: DSTN overrules forcecrt2type */
2115 XGIfb_crt2type = DISPTYPE_LCD;
2116 } else if (!strncmp(this_opt, "pdc:", 4)) {
2117 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2118 if (XGIfb_pdc & ~0x3c) {
2119 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2122 } else if (!strncmp(this_opt, "noypan", 6)) {
2124 } else if (!strncmp(this_opt, "userom:", 7)) {
2125 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2126 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2127 /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2129 XGIfb_search_mode(this_opt);
2130 /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2133 /* TW: Panning only with acceleration */
2137 printk("\nxgifb: outa xgifb_setup 3450");
2141 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
2143 void __iomem *rom_address;
2144 unsigned char *rom_copy;
2147 rom_address = pci_map_rom(dev, &rom_size);
2148 if (rom_address == NULL)
2151 rom_copy = vzalloc(XGIFB_ROM_SIZE);
2152 if (rom_copy == NULL)
2155 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
2156 memcpy_fromio(rom_copy, rom_address, rom_size);
2159 pci_unmap_rom(dev, rom_address);
2163 static int __devinit xgifb_probe(struct pci_dev *pdev,
2164 const struct pci_device_id *ent)
2173 XGIfb_registered = 0;
2175 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2176 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2180 xgi_video_info.chip_id = pdev->device;
2181 pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2182 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2184 xgi_video_info.pcibus = pdev->bus->number;
2185 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2186 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2187 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2188 xgi_video_info.subsysdevice = pdev->subsystem_device;
2190 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2191 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2192 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2193 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2194 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2195 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2196 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2197 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2199 if (pci_enable_device(pdev)) {
2204 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2206 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2207 reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD);
2209 if (reg1 != 0xa1) { /*I/O error */
2210 printk("\nXGIfb: I/O error!!!");
2215 switch (xgi_video_info.chip_id) {
2216 case PCI_DEVICE_ID_XG_20:
2217 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2218 CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
2219 if (CR48&GPIOG_READ)
2220 xgi_video_info.chip = XG21;
2222 xgi_video_info.chip = XG20;
2223 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2225 case PCI_DEVICE_ID_XG_40:
2226 xgi_video_info.chip = XG40;
2227 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2229 case PCI_DEVICE_ID_XG_41:
2230 xgi_video_info.chip = XG41;
2231 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2233 case PCI_DEVICE_ID_XG_42:
2234 xgi_video_info.chip = XG42;
2235 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2237 case PCI_DEVICE_ID_XG_27:
2238 xgi_video_info.chip = XG27;
2239 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2246 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
2247 XGIhw_ext.jChipType = xgi_video_info.chip;
2249 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
2250 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
2251 if (XGIhw_ext.pjVirtualRomBase)
2252 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
2254 printk(KERN_INFO "XGIfb: Video ROM not found\n");
2256 XGIhw_ext.pjVirtualRomBase = NULL;
2257 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2259 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2261 if (XGIfb_get_dram_size()) {
2262 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
2267 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2268 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
2269 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
2270 /* Enable 2D accelerator engine */
2271 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
2274 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
2276 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
2277 printk("unable request memory size %x", xgi_video_info.video_size);
2278 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
2279 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
2284 if (!request_mem_region(xgi_video_info.mmio_base,
2285 xgi_video_info.mmio_size,
2287 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
2292 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
2293 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
2294 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
2295 xgi_video_info.mmio_size);
2297 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
2298 xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
2300 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
2301 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
2302 xgi_video_info.mmio_size / 1024);
2303 printk("XGIfb: XGIInitNew() ...");
2304 if (XGIInitNew(&XGIhw_ext))
2309 xgi_video_info.mtrr = (unsigned int) 0;
2311 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2312 xgi_video_info.hasVB = HASVB_NONE;
2313 if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
2314 xgi_video_info.hasVB = HASVB_NONE;
2315 } else if (xgi_video_info.chip == XG21) {
2316 CR38 = xgifb_reg_get(XGICR, 0x38);
2317 if ((CR38&0xE0) == 0xC0) {
2318 xgi_video_info.disp_state = DISPTYPE_LCD;
2319 if (!XGIfb_GetXG21LVDSData()) {
2321 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
2322 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
2323 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
2324 xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
2328 } else if ((CR38&0xE0) == 0x60) {
2329 xgi_video_info.hasVB = HASVB_CHRONTEL;
2331 xgi_video_info.hasVB = HASVB_NONE;
2334 XGIfb_get_VB_type();
2337 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
2339 XGIhw_ext.ulExternalChip = 0;
2341 switch (xgi_video_info.hasVB) {
2343 reg = xgifb_reg_get(XGIPART4, 0x01);
2345 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2346 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2347 } else if (reg >= 0xD0) {
2348 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2349 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
2351 /* else if (reg >= 0xB0) {
2352 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
2353 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2354 printk("XGIfb: XGI301B bridge detected\n");
2357 XGIhw_ext.ujVBChipID = VB_CHIP_301;
2358 printk("XGIfb: XGI301 bridge detected\n");
2362 reg = xgifb_reg_get(XGIPART4, 0x01);
2364 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2365 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2366 } else if (reg >= 0xD0) {
2367 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2368 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2369 } else if (reg >= 0xB0) {
2370 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2372 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
2375 XGIhw_ext.ujVBChipID = VB_CHIP_302;
2376 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
2380 XGIhw_ext.ulExternalChip = 0x1;
2381 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
2383 case HASVB_TRUMPION:
2384 XGIhw_ext.ulExternalChip = 0x2;
2385 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
2387 case HASVB_CHRONTEL:
2388 XGIhw_ext.ulExternalChip = 0x4;
2389 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
2391 case HASVB_LVDS_CHRONTEL:
2392 XGIhw_ext.ulExternalChip = 0x5;
2393 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2396 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
2400 if (xgi_video_info.hasVB != HASVB_NONE)
2403 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2405 xgi_video_info.disp_state |= DISPMODE_SINGLE;
2407 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
2409 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
2412 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2414 reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2416 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
2420 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
2424 XGIfb_detectedpdc = 0;
2426 XGIfb_detectedlcda = 0xff;
2428 /* TW: Try to find about LCDA */
2430 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
2431 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2432 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
2434 tmp = xgifb_reg_get(XGICR, 0x34);
2436 /* Currently on LCDA? (Some BIOSes leave CR38) */
2437 tmp = xgifb_reg_get(XGICR, 0x38);
2438 if ((tmp & 0x03) == 0x03) {
2439 /* XGI_Pr.XGI_UseLCDA = 1; */
2441 /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
2442 tmp = xgifb_reg_get(XGICR, 0x35);
2444 /* XGI_Pr.XGI_UseLCDA = 1; */
2446 tmp = xgifb_reg_get(XGICR, 0x30);
2448 tmp = xgifb_reg_get(XGIPART1, 0x13);
2450 /* XGI_Pr.XGI_UseLCDA = 1; */
2459 if (xgifb_mode_idx >= 0)
2460 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
2462 if (xgifb_mode_idx < 0) {
2463 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2465 xgifb_mode_idx = DEFAULT_LCDMODE;
2466 if (xgi_video_info.chip == XG21)
2467 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
2470 xgifb_mode_idx = DEFAULT_TVMODE;
2473 xgifb_mode_idx = DEFAULT_MODE;
2478 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
2480 if (xgi_video_info.refresh_rate == 0)
2481 xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
2482 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
2483 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
2484 xgi_video_info.refresh_rate = 60;
2487 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
2488 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
2489 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
2490 xgi_video_info.org_x = xgi_video_info.org_y = 0;
2491 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
2492 switch (xgi_video_info.video_bpp) {
2494 xgi_video_info.DstColor = 0x0000;
2495 xgi_video_info.XGI310_AccelDepth = 0x00000000;
2496 xgi_video_info.video_cmap_len = 256;
2499 xgi_video_info.DstColor = 0x8000;
2500 xgi_video_info.XGI310_AccelDepth = 0x00010000;
2501 xgi_video_info.video_cmap_len = 16;
2504 xgi_video_info.DstColor = 0xC000;
2505 xgi_video_info.XGI310_AccelDepth = 0x00020000;
2506 xgi_video_info.video_cmap_len = 16;
2509 xgi_video_info.video_cmap_len = 16;
2510 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
2514 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
2515 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
2516 xgi_video_info.refresh_rate);
2518 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
2519 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
2520 default_var.bits_per_pixel = xgi_video_info.video_bpp;
2522 XGIfb_bpp_to_var(&default_var);
2524 default_var.pixclock = (u32) (1000000000 /
2525 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
2526 XGIfb_mode_no, XGIfb_rate_idx));
2528 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
2529 XGIfb_mode_no, XGIfb_rate_idx,
2530 &default_var.left_margin, &default_var.right_margin,
2531 &default_var.upper_margin, &default_var.lower_margin,
2532 &default_var.hsync_len, &default_var.vsync_len,
2533 &default_var.sync, &default_var.vmode)) {
2535 if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
2536 default_var.yres <<= 1;
2537 default_var.yres_virtual <<= 1;
2538 } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
2539 default_var.pixclock >>= 1;
2540 default_var.yres >>= 1;
2541 default_var.yres_virtual >>= 1;
2546 fb_info->flags = FBINFO_FLAG_DEFAULT;
2547 fb_info->var = default_var;
2548 fb_info->fix = XGIfb_fix;
2549 fb_info->par = &xgi_video_info;
2550 fb_info->screen_base = xgi_video_info.video_vbase;
2551 fb_info->fbops = &XGIfb_ops;
2552 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
2553 fb_info->pseudo_palette = pseudo_palette;
2555 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2558 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
2559 (unsigned int) xgi_video_info.video_size,
2560 MTRR_TYPE_WRCOMB, 1);
2561 if (xgi_video_info.mtrr)
2562 printk(KERN_INFO "XGIfb: Added MTRRs\n");
2565 if (register_framebuffer(fb_info) < 0) {
2570 XGIfb_registered = 1;
2572 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
2573 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
2582 iounmap(xgi_video_info.mmio_vbase);
2583 iounmap(xgi_video_info.video_vbase);
2584 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2586 release_mem_region(xgi_video_info.video_base,
2587 xgi_video_info.video_size);
2589 vfree(XGIhw_ext.pjVirtualRomBase);
2590 framebuffer_release(fb_info);
2594 /*****************************************************/
2595 /* PCI DEVICE HANDLING */
2596 /*****************************************************/
2598 static void __devexit xgifb_remove(struct pci_dev *pdev)
2600 unregister_framebuffer(fb_info);
2601 iounmap(xgi_video_info.mmio_vbase);
2602 iounmap(xgi_video_info.video_vbase);
2603 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2604 release_mem_region(xgi_video_info.video_base,
2605 xgi_video_info.video_size);
2606 vfree(XGIhw_ext.pjVirtualRomBase);
2607 framebuffer_release(fb_info);
2608 pci_set_drvdata(pdev, NULL);
2611 static struct pci_driver xgifb_driver = {
2613 .id_table = xgifb_pci_table,
2614 .probe = xgifb_probe,
2615 .remove = __devexit_p(xgifb_remove)
2618 XGIINITSTATIC int __init xgifb_init(void)
2620 char *option = NULL;
2622 if (fb_get_options("xgifb", &option))
2624 XGIfb_setup(option);
2626 return pci_register_driver(&xgifb_driver);
2630 module_init(xgifb_init);
2633 /*****************************************************/
2635 /*****************************************************/
2639 static char *mode = NULL;
2640 static int vesa = 0;
2641 static unsigned int rate = 0;
2642 static unsigned int mem = 0;
2643 static char *forcecrt2type = NULL;
2644 static int forcecrt1 = -1;
2645 static int pdc = -1;
2646 static int pdc1 = -1;
2647 static int noypan = -1;
2648 static int userom = -1;
2649 static int useoem = -1;
2650 static char *tvstandard = NULL;
2651 static int nocrt2rate = 0;
2652 static int scalelcd = -1;
2653 static char *specialtiming = NULL;
2654 static int lvdshl = -1;
2655 static int tvxposoffset = 0, tvyposoffset = 0;
2656 #if !defined(__i386__) && !defined(__x86_64__)
2657 static int resetcard = 0;
2658 static int videoram = 0;
2661 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2662 MODULE_LICENSE("GPL");
2663 MODULE_AUTHOR("XGITECH , Others");
2665 module_param(mem, int, 0);
2666 module_param(noypan, int, 0);
2667 module_param(userom, int, 0);
2668 module_param(useoem, int, 0);
2669 module_param(mode, charp, 0);
2670 module_param(vesa, int, 0);
2671 module_param(rate, int, 0);
2672 module_param(forcecrt1, int, 0);
2673 module_param(forcecrt2type, charp, 0);
2674 module_param(scalelcd, int, 0);
2675 module_param(pdc, int, 0);
2676 module_param(pdc1, int, 0);
2677 module_param(specialtiming, charp, 0);
2678 module_param(lvdshl, int, 0);
2679 module_param(tvstandard, charp, 0);
2680 module_param(tvxposoffset, int, 0);
2681 module_param(tvyposoffset, int, 0);
2682 module_param(filter, int, 0);
2683 module_param(nocrt2rate, int, 0);
2684 #if !defined(__i386__) && !defined(__x86_64__)
2685 module_param(resetcard, int, 0);
2686 module_param(videoram, int, 0);
2689 MODULE_PARM_DESC(noypan,
2690 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
2691 "will be performed by redrawing the screen. (default: 0)\n");
2693 MODULE_PARM_DESC(mode,
2694 "\nSelects the desired default display mode in the format XxYxDepth,\n"
2695 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
2696 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
2697 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
2699 MODULE_PARM_DESC(vesa,
2700 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
2701 "0x117 (default: 0x0103)\n");
2703 MODULE_PARM_DESC(rate,
2704 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
2705 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
2706 "will be ignored (default: 60)\n");
2708 MODULE_PARM_DESC(forcecrt1,
2709 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
2710 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
2711 "0=CRT1 OFF) (default: [autodetected])\n");
2713 MODULE_PARM_DESC(forcecrt2type,
2714 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
2715 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
2716 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
2717 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
2718 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
2719 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
2720 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
2721 "depends on the very hardware in use. (default: [autodetected])\n");
2723 MODULE_PARM_DESC(scalelcd,
2724 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
2725 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
2726 "show black bars around the image, TMDS panels will probably do the scaling\n"
2727 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
2729 MODULE_PARM_DESC(pdc,
2730 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
2731 "should detect this correctly in most cases; however, sometimes this is not\n"
2732 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
2733 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
2734 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
2735 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
2737 MODULE_PARM_DESC(pdc1,
2738 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
2739 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
2740 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
2741 "implemented yet.\n");
2743 MODULE_PARM_DESC(specialtiming,
2744 "\nPlease refer to documentation for more information on this option.\n");
2746 MODULE_PARM_DESC(lvdshl,
2747 "\nPlease refer to documentation for more information on this option.\n");
2749 MODULE_PARM_DESC(tvstandard,
2750 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
2751 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
2753 MODULE_PARM_DESC(tvxposoffset,
2754 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
2757 MODULE_PARM_DESC(tvyposoffset,
2758 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
2761 MODULE_PARM_DESC(filter,
2762 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2763 "(Possible values 0-7, default: [no filter])\n");
2765 MODULE_PARM_DESC(nocrt2rate,
2766 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
2767 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
2769 static int __init xgifb_init_module(void)
2771 printk("\nXGIfb_init_module");
2773 XGIfb_search_mode(mode);
2774 else if (vesa != -1)
2775 XGIfb_search_vesamode(vesa);
2777 return xgifb_init();
2780 static void __exit xgifb_remove_module(void)
2782 pci_unregister_driver(&xgifb_driver);
2783 printk(KERN_DEBUG "xgifb: Module unloaded\n");
2786 module_init(xgifb_init_module);
2787 module_exit(xgifb_remove_module);
2789 #endif /* /MODULE */