cnic: Add FCoE support on 57712
[linux-2.6/libata-dev.git] / drivers / staging / xgifb / XGI_main_26.c
blob4f73d095c3ac567540bde50fae8fbf703d145e12
1 /*
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.
5 */
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>
15 #include <linux/mm.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/fb.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>
28 #include <linux/fs.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
32 #ifndef XGIFB_PAN
33 #define XGIFB_PAN
34 #endif
36 #include <asm/io.h>
37 #ifdef CONFIG_MTRR
38 #include <asm/mtrr.h>
39 #endif
41 #include "XGIfb.h"
42 #include "vgatypes.h"
43 #include "XGI_main.h"
44 #include "vb_util.h"
46 int XGIfb_accel = 0;
48 #define Index_CR_GPIO_Reg1 0x48
49 #define Index_CR_GPIO_Reg2 0x49
50 #define Index_CR_GPIO_Reg3 0x4a
52 #define GPIOG_EN (1<<6)
53 #define GPIOG_WRITE (1<<6)
54 #define GPIOG_READ (1<<1)
55 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
57 /* -------------------- Macro definitions ---------------------------- */
59 #undef XGIFBDEBUG
61 #ifdef XGIFBDEBUG
62 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
63 #else
64 #define DPRINTK(fmt, args...)
65 #endif
67 #ifdef XGIFBDEBUG
68 static void dumpVGAReg(void)
70 u8 i, reg;
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);
140 #else
141 static inline void dumpVGAReg(void)
144 #endif
146 /* data for XGI components */
147 struct video_info xgi_video_info;
149 #if 1
150 #define DEBUGPRN(x)
151 #else
152 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
153 #endif
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; */
166 int Clock;
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) ;
175 if (!temp) {
176 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
177 return 65000;
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)
186 ClockIndex &= 0x3F;
188 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
190 return Clock;
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,
198 u32 *vmode)
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);
215 if (!temp)
216 return 0;
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);
229 A = HT + 5;
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;
238 E = HDE + 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);
244 F = HRS - E - 3;
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);
270 D = B - F - C;
272 *left_margin = D * 8;
273 *right_margin = F * 8;
274 *hsync_len = C * 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];
282 /* Vertical total */
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);
286 A = VT + 2;
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;
298 E = VDE + 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);
306 F = VRS + 1 - E;
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);
331 D = B - F - C;
333 *upper_margin = D;
334 *lower_margin = F;
335 *vsync_len = C;
337 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
338 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
339 else
340 *sync |= FB_SYNC_VERT_HIGH_ACT;
342 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
343 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
344 else
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;
350 else {
351 j = 0;
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
356 & DoubleScanMode) {
357 *vmode = FB_VMODE_DOUBLE;
359 break;
361 j++;
365 return 1;
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)
397 u32 data;
399 data = inl(port);
400 return data;
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;
412 if (!set)
413 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
414 else
415 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
417 if (!init) {
418 init = 1;
419 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
420 pdev);
421 if (pdev) {
422 valid_pdev = 1;
423 pci_dev_put(pdev);
427 if (!valid_pdev) {
428 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
429 xgi_video_info.chip_id);
430 return 0;
433 if (set == 0)
434 pci_read_config_dword(pdev, offset, (u32 *) value);
435 else
436 pci_write_config_dword(pdev, offset, (u32)(*value));
438 return 1;
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;
447 u16 nbridge_id = 0;
449 if (!init) {
450 init = 1;
451 switch (xgi_video_info.chip) {
452 case XGI_540:
453 nbridge_id = PCI_DEVICE_ID_XG_540;
454 break;
455 case XGI_630:
456 nbridge_id = PCI_DEVICE_ID_XG_630;
457 break;
458 case XGI_730:
459 nbridge_id = PCI_DEVICE_ID_XG_730;
460 break;
461 case XGI_550:
462 nbridge_id = PCI_DEVICE_ID_XG_550;
463 break;
464 case XGI_650:
465 nbridge_id = PCI_DEVICE_ID_XG_650;
466 break;
467 case XGI_740:
468 nbridge_id = PCI_DEVICE_ID_XG_740;
469 break;
470 default:
471 nbridge_id = 0;
472 break;
475 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
476 if (pdev)
477 valid_pdev = 1;
480 if (!valid_pdev) {
481 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
482 nbridge_id);
483 return 0;
486 if (set == 0)
487 pci_read_config_dword(pdev, offset, (u32 *)value);
488 else
489 pci_write_config_dword(pdev, offset, (u32)(*value));
491 return 1;
494 /* ------------------ Internal helper routines ----------------- */
496 static void XGIfb_search_mode(const char *name)
498 int i = 0, j = 0, l;
500 if (name == NULL) {
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)
505 == DISPTYPE_LCD)) {
506 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
508 return;
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)
516 == DISPTYPE_LCD)) {
517 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
519 return;
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)) {
525 xgifb_mode_idx = i;
526 j = 1;
527 break;
529 i++;
531 if (!j)
532 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
535 static void XGIfb_search_vesamode(unsigned int vesamode)
537 int i = 0, j = 0;
539 if (vesamode == 0) {
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)
545 == DISPTYPE_LCD)) {
546 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
548 return;
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)) {
556 xgifb_mode_idx = i;
557 j = 1;
558 break;
560 i++;
562 if (!j)
563 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
566 static int XGIfb_GetXG21LVDSData(void)
568 u8 tmp;
569 unsigned char *pData;
570 int i, j, k;
572 inXGIIDXREG(XGISR, 0x1e, tmp);
573 outXGIIDXREG(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);
578 j = pData[i - 1];
579 if (j == 0xff)
580 j = 1;
582 k = 0;
583 do {
584 XGI21_LCDCapList[k].LVDS_Capability = pData[i]
585 | (pData[i + 1] << 8);
586 XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
587 + 3] << 8);
588 XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
589 + 5] << 8);
590 XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
591 + 7] << 8);
592 XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
593 + 9] << 8);
594 XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
595 + 11] << 8);
596 XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
597 + 13] << 8);
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];
609 i += 25;
610 j--;
611 k++;
612 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
613 / sizeof(struct XGI21_LVDSCapStruct))));
614 return 1;
616 return 0;
619 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
622 int found_mode = 0;
623 int XGIfb_mode_idx = 0;
625 found_mode = 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;
635 found_mode = 1;
636 break;
638 XGIfb_mode_idx++;
640 if (!found_mode)
641 XGIfb_mode_idx = 0;
643 return XGIfb_mode_idx;
646 static int XGIfb_validate_mode(int myindex)
648 u16 xres, yres;
650 if (xgi_video_info.chip == XG21) {
651 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
652 == DISPTYPE_LCD) {
653 xres = XGI21_LCDCapList[0].LVDSHDE;
654 yres = XGI21_LCDCapList[0].LVDSVDE;
655 if (XGIbios_mode[myindex].xres > xres)
656 return -1;
657 if (XGIbios_mode[myindex].yres > yres)
658 return -1;
659 if ((XGIbios_mode[myindex].xres < xres)
660 && (XGIbios_mode[myindex].yres < yres)) {
661 if (XGIbios_mode[myindex].bpp > 8)
662 return -1;
666 return myindex;
670 /* FIXME: for now, all is valid on XG27 */
671 if (xgi_video_info.chip == XG27)
672 return myindex;
674 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
675 return -1;
677 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
678 case DISPTYPE_LCD:
679 switch (XGIhw_ext.ulCRT2LCDType) {
680 case LCD_640x480:
681 xres = 640;
682 yres = 480;
683 break;
684 case LCD_800x600:
685 xres = 800;
686 yres = 600;
687 break;
688 case LCD_1024x600:
689 xres = 1024;
690 yres = 600;
691 break;
692 case LCD_1024x768:
693 xres = 1024;
694 yres = 768;
695 break;
696 case LCD_1152x768:
697 xres = 1152;
698 yres = 768;
699 break;
700 case LCD_1280x960:
701 xres = 1280;
702 yres = 960;
703 break;
704 case LCD_1280x768:
705 xres = 1280;
706 yres = 768;
707 break;
708 case LCD_1280x1024:
709 xres = 1280;
710 yres = 1024;
711 break;
712 case LCD_1400x1050:
713 xres = 1400;
714 yres = 1050;
715 break;
716 case LCD_1600x1200:
717 xres = 1600;
718 yres = 1200;
719 break;
720 /* case LCD_320x480: */ /* TW: FSTN */
722 xres = 320;
723 yres = 480;
724 break;
726 default:
727 xres = 0;
728 yres = 0;
729 break;
731 if (XGIbios_mode[myindex].xres > xres)
732 return -1;
733 if (XGIbios_mode[myindex].yres > yres)
734 return -1;
735 if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
736 (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
737 switch (XGIbios_mode[myindex].xres) {
738 case 512:
739 if (XGIbios_mode[myindex].yres != 512)
740 return -1;
741 if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
742 return -1;
743 break;
744 case 640:
745 if ((XGIbios_mode[myindex].yres != 400)
746 && (XGIbios_mode[myindex].yres
747 != 480))
748 return -1;
749 break;
750 case 800:
751 if (XGIbios_mode[myindex].yres != 600)
752 return -1;
753 break;
754 case 1024:
755 if ((XGIbios_mode[myindex].yres != 600)
756 && (XGIbios_mode[myindex].yres
757 != 768))
758 return -1;
759 if ((XGIbios_mode[myindex].yres == 600)
760 && (XGIhw_ext.ulCRT2LCDType
761 != LCD_1024x600))
762 return -1;
763 break;
764 case 1152:
765 if ((XGIbios_mode[myindex].yres) != 768)
766 return -1;
767 if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
768 return -1;
769 break;
770 case 1280:
771 if ((XGIbios_mode[myindex].yres != 768)
772 && (XGIbios_mode[myindex].yres
773 != 1024))
774 return -1;
775 if ((XGIbios_mode[myindex].yres == 768)
776 && (XGIhw_ext.ulCRT2LCDType
777 != LCD_1280x768))
778 return -1;
779 break;
780 case 1400:
781 if (XGIbios_mode[myindex].yres != 1050)
782 return -1;
783 break;
784 case 1600:
785 if (XGIbios_mode[myindex].yres != 1200)
786 return -1;
787 break;
788 default:
789 return -1;
791 } else {
792 switch (XGIbios_mode[myindex].xres) {
793 case 512:
794 if (XGIbios_mode[myindex].yres != 512)
795 return -1;
796 break;
797 case 640:
798 if ((XGIbios_mode[myindex].yres != 400)
799 && (XGIbios_mode[myindex].yres
800 != 480))
801 return -1;
802 break;
803 case 800:
804 if (XGIbios_mode[myindex].yres != 600)
805 return -1;
806 break;
807 case 1024:
808 if (XGIbios_mode[myindex].yres != 768)
809 return -1;
810 break;
811 case 1280:
812 if ((XGIbios_mode[myindex].yres != 960)
813 && (XGIbios_mode[myindex].yres
814 != 1024))
815 return -1;
816 if (XGIbios_mode[myindex].yres == 960) {
817 if (XGIhw_ext.ulCRT2LCDType
818 == LCD_1400x1050)
819 return -1;
821 break;
822 case 1400:
823 if (XGIbios_mode[myindex].yres != 1050)
824 return -1;
825 break;
826 case 1600:
827 if (XGIbios_mode[myindex].yres != 1200)
828 return -1;
829 break;
830 default:
831 return -1;
834 break;
835 case DISPTYPE_TV:
836 switch (XGIbios_mode[myindex].xres) {
837 case 512:
838 case 640:
839 case 800:
840 break;
841 case 720:
842 if (xgi_video_info.TV_type == TVMODE_NTSC) {
843 if (XGIbios_mode[myindex].yres != 480)
844 return -1;
845 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
846 if (XGIbios_mode[myindex].yres != 576)
847 return -1;
849 /* TW: LVDS/CHRONTEL does not support 720 */
850 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
851 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
852 return -1;
854 break;
855 case 1024:
856 if (xgi_video_info.TV_type == TVMODE_NTSC) {
857 if (XGIbios_mode[myindex].bpp == 32)
858 return -1;
860 /* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) */
861 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
862 || xgi_video_info.hasVB == HASVB_CHRONTEL) {
863 if (xgi_video_info.chip < XGI_315H)
864 return -1;
866 break;
867 default:
868 return -1;
870 break;
871 case DISPTYPE_CRT2:
872 if (XGIbios_mode[myindex].xres > 1280)
873 return -1;
874 break;
876 return myindex;
880 static void XGIfb_search_crt2type(const char *name)
882 int i = 0;
884 if (name == NULL)
885 return;
887 while (XGI_crt2type[i].type_no != -1) {
888 if (!strcmp(name, XGI_crt2type[i].name)) {
889 XGIfb_crt2type = XGI_crt2type[i].type_no;
890 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
891 break;
893 i++;
895 if (XGIfb_crt2type < 0)
896 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
899 static void XGIfb_search_queuemode(const char *name)
901 int i = 0;
903 if (name == NULL)
904 return;
906 while (XGI_queuemode[i].type_no != -1) {
907 if (!strcmp(name, XGI_queuemode[i].name)) {
908 XGIfb_queuemode = XGI_queuemode[i].type_no;
909 break;
911 i++;
913 if (XGIfb_queuemode < 0)
914 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
917 static u8 XGIfb_search_refresh_rate(unsigned int rate)
919 u16 xres, yres;
920 int i = 0;
922 xres = XGIbios_mode[xgifb_mode_idx].xres;
923 yres = XGIbios_mode[xgifb_mode_idx].yres;
925 XGIfb_rate_idx = 0;
926 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
927 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres
928 == yres)) {
929 if (XGIfb_vrate[i].refresh == rate) {
930 XGIfb_rate_idx = XGIfb_vrate[i].idx;
931 break;
932 } else if (XGIfb_vrate[i].refresh > rate) {
933 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
934 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
935 rate, XGIfb_vrate[i].refresh);
936 XGIfb_rate_idx = XGIfb_vrate[i].idx;
937 xgi_video_info.refresh_rate
938 = XGIfb_vrate[i].refresh;
939 } else if (((rate - XGIfb_vrate[i - 1].refresh)
940 <= 2) && (XGIfb_vrate[i].idx
941 != 1)) {
942 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
943 rate, XGIfb_vrate[i-1].refresh);
944 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
945 xgi_video_info.refresh_rate
946 = XGIfb_vrate[i - 1].refresh;
948 break;
949 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
950 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
951 rate, XGIfb_vrate[i].refresh);
952 XGIfb_rate_idx = XGIfb_vrate[i].idx;
953 break;
956 i++;
958 if (XGIfb_rate_idx > 0) {
959 return XGIfb_rate_idx;
960 } else {
961 printk(KERN_INFO
962 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
963 return 0;
967 static void XGIfb_search_tvstd(const char *name)
969 int i = 0;
971 if (name == NULL)
972 return;
974 while (XGI_tvtype[i].type_no != -1) {
975 if (!strcmp(name, XGI_tvtype[i].name)) {
976 XGIfb_tvmode = XGI_tvtype[i].type_no;
977 break;
979 i++;
983 static unsigned char XGIfb_bridgeisslave(void)
985 unsigned char usScratchP1_00;
987 if (xgi_video_info.hasVB == HASVB_NONE)
988 return 0;
990 inXGIIDXREG(XGIPART1, 0x00, usScratchP1_00);
991 if ((usScratchP1_00 & 0x50) == 0x10)
992 return 1;
993 else
994 return 0;
997 static unsigned char XGIfbcheckvretracecrt1(void)
999 unsigned char temp;
1001 inXGIIDXREG(XGICR, 0x17, temp);
1002 if (!(temp & 0x80))
1003 return 0;
1005 inXGIIDXREG(XGISR, 0x1f, temp);
1006 if (temp & 0xc0)
1007 return 0;
1009 if (inXGIREG(XGIINPSTAT) & 0x08)
1010 return 1;
1011 else
1012 return 0;
1015 static unsigned char XGIfbcheckvretracecrt2(void)
1017 unsigned char temp;
1018 if (xgi_video_info.hasVB == HASVB_NONE)
1019 return 0;
1020 inXGIIDXREG(XGIPART1, 0x30, temp);
1021 if (temp & 0x02)
1022 return 0;
1023 else
1024 return 1;
1027 static unsigned char XGIfb_CheckVBRetrace(void)
1029 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1030 if (XGIfb_bridgeisslave())
1031 return XGIfbcheckvretracecrt1();
1032 else
1033 return XGIfbcheckvretracecrt2();
1035 return XGIfbcheckvretracecrt1();
1038 /* ----------- FBDev related routines for all series ----------- */
1040 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1042 switch (var->bits_per_pixel) {
1043 case 8:
1044 var->red.offset = var->green.offset = var->blue.offset = 0;
1045 var->red.length = var->green.length = var->blue.length = 6;
1046 xgi_video_info.video_cmap_len = 256;
1047 break;
1048 case 16:
1049 var->red.offset = 11;
1050 var->red.length = 5;
1051 var->green.offset = 5;
1052 var->green.length = 6;
1053 var->blue.offset = 0;
1054 var->blue.length = 5;
1055 var->transp.offset = 0;
1056 var->transp.length = 0;
1057 xgi_video_info.video_cmap_len = 16;
1058 break;
1059 case 32:
1060 var->red.offset = 16;
1061 var->red.length = 8;
1062 var->green.offset = 8;
1063 var->green.length = 8;
1064 var->blue.offset = 0;
1065 var->blue.length = 8;
1066 var->transp.offset = 24;
1067 var->transp.length = 8;
1068 xgi_video_info.video_cmap_len = 16;
1069 break;
1073 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1074 struct fb_info *info)
1077 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1078 + var->hsync_len;
1079 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1080 + var->vsync_len;
1081 #if defined(__powerpc__)
1082 u8 sr_data, cr_data;
1083 #endif
1084 unsigned int drate = 0, hrate = 0;
1085 int found_mode = 0;
1086 int old_mode;
1087 /* unsigned char reg, reg1; */
1089 DEBUGPRN("Inside do_set_var");
1090 /* 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); */
1092 info->var.xres_virtual = var->xres_virtual;
1093 info->var.yres_virtual = var->yres_virtual;
1094 info->var.bits_per_pixel = var->bits_per_pixel;
1096 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1097 vtotal <<= 1;
1098 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1099 vtotal <<= 2;
1100 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1101 /* vtotal <<= 1; */
1102 /* var->yres <<= 1; */
1105 if (!htotal || !vtotal) {
1106 DPRINTK("XGIfb: Invalid 'var' information\n");
1107 return -EINVAL;
1108 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1109 var->pixclock, htotal, vtotal);
1111 if (var->pixclock && htotal && vtotal) {
1112 drate = 1000000000 / var->pixclock;
1113 hrate = (drate * 1000) / htotal;
1114 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1115 / vtotal);
1116 } else {
1117 xgi_video_info.refresh_rate = 60;
1120 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1121 var->xres, var->yres, var->bits_per_pixel, xgi_video_info.refresh_rate);
1123 old_mode = xgifb_mode_idx;
1124 xgifb_mode_idx = 0;
1126 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1127 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1128 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1129 && (XGIbios_mode[xgifb_mode_idx].yres
1130 == var->yres)
1131 && (XGIbios_mode[xgifb_mode_idx].bpp
1132 == var->bits_per_pixel)) {
1133 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1134 found_mode = 1;
1135 break;
1137 xgifb_mode_idx++;
1140 if (found_mode)
1141 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1142 else
1143 xgifb_mode_idx = -1;
1145 if (xgifb_mode_idx < 0) {
1146 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1147 var->yres, var->bits_per_pixel);
1148 xgifb_mode_idx = old_mode;
1149 return -EINVAL;
1152 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1153 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1154 xgi_video_info.refresh_rate = 60;
1157 if (isactive) {
1159 XGIfb_pre_setmode();
1160 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1161 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1162 return -EINVAL;
1164 info->fix.line_length = ((info->var.xres_virtual
1165 * info->var.bits_per_pixel) >> 6);
1167 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1169 outXGIIDXREG(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1170 outXGIIDXREG(XGISR, 0x0E, (info->fix.line_length & 0xff00) >> 8);
1172 XGIfb_post_setmode();
1174 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1175 XGIbios_mode[xgifb_mode_idx].xres,
1176 XGIbios_mode[xgifb_mode_idx].yres,
1177 XGIbios_mode[xgifb_mode_idx].bpp,
1178 xgi_video_info.refresh_rate);
1180 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1181 xgi_video_info.video_vwidth = info->var.xres_virtual;
1182 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1183 xgi_video_info.video_vheight = info->var.yres_virtual;
1184 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1185 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1186 xgi_video_info.video_linelength = info->var.xres_virtual
1187 * (xgi_video_info.video_bpp >> 3);
1188 xgi_video_info.accel = 0;
1189 if (XGIfb_accel) {
1190 xgi_video_info.accel = (var->accel_flags
1191 & FB_ACCELF_TEXT) ? -1 : 0;
1193 switch (xgi_video_info.video_bpp) {
1194 case 8:
1195 xgi_video_info.DstColor = 0x0000;
1196 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1197 xgi_video_info.video_cmap_len = 256;
1198 #if defined(__powerpc__)
1199 inXGIIDXREG(XGICR, 0x4D, cr_data);
1200 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1201 #endif
1202 break;
1203 case 16:
1204 xgi_video_info.DstColor = 0x8000;
1205 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1206 #if defined(__powerpc__)
1207 inXGIIDXREG(XGICR, 0x4D, cr_data);
1208 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1209 #endif
1210 xgi_video_info.video_cmap_len = 16;
1211 break;
1212 case 32:
1213 xgi_video_info.DstColor = 0xC000;
1214 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1215 xgi_video_info.video_cmap_len = 16;
1216 #if defined(__powerpc__)
1217 inXGIIDXREG(XGICR, 0x4D, cr_data);
1218 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1219 #endif
1220 break;
1221 default:
1222 xgi_video_info.video_cmap_len = 16;
1223 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1224 xgi_video_info.accel = 0;
1225 break;
1228 XGIfb_bpp_to_var(var); /*update ARGB info*/
1229 DEBUGPRN("End of do_set_var");
1231 dumpVGAReg();
1232 return 0;
1235 #ifdef XGIFB_PAN
1236 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1238 unsigned int base;
1240 /* printk("Inside pan_var"); */
1242 if (var->xoffset > (var->xres_virtual - var->xres)) {
1243 /* printk("Pan: xo: %d xv %d xr %d\n",
1244 var->xoffset, var->xres_virtual, var->xres); */
1245 return -EINVAL;
1247 if (var->yoffset > (var->yres_virtual - var->yres)) {
1248 /* printk("Pan: yo: %d yv %d yr %d\n",
1249 var->yoffset, var->yres_virtual, var->yres); */
1250 return -EINVAL;
1252 base = var->yoffset * var->xres_virtual + var->xoffset;
1254 /* calculate base bpp dep. */
1255 switch (var->bits_per_pixel) {
1256 case 16:
1257 base >>= 1;
1258 break;
1259 case 32:
1260 break;
1261 case 8:
1262 default:
1263 base >>= 2;
1264 break;
1267 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1269 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1270 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1271 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1272 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1273 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1275 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1276 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1277 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1278 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1279 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1280 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1282 /* printk("End of pan_var"); */
1283 return 0;
1285 #endif
1287 void XGI_dispinfo(struct ap_data *rec)
1289 rec->minfo.bpp = xgi_video_info.video_bpp;
1290 rec->minfo.xres = xgi_video_info.video_width;
1291 rec->minfo.yres = xgi_video_info.video_height;
1292 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1293 rec->minfo.v_yres = xgi_video_info.video_vheight;
1294 rec->minfo.org_x = xgi_video_info.org_x;
1295 rec->minfo.org_y = xgi_video_info.org_y;
1296 rec->minfo.vrate = xgi_video_info.refresh_rate;
1297 rec->iobase = xgi_video_info.vga_base - 0x30;
1298 rec->mem_size = xgi_video_info.video_size;
1299 rec->disp_state = xgi_video_info.disp_state;
1300 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1301 rec->hasVB = xgi_video_info.hasVB;
1302 rec->TV_type = xgi_video_info.TV_type;
1303 rec->TV_plug = xgi_video_info.TV_plug;
1304 rec->chip = xgi_video_info.chip;
1307 static int XGIfb_open(struct fb_info *info, int user)
1309 return 0;
1312 static int XGIfb_release(struct fb_info *info, int user)
1314 return 0;
1317 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1319 int rc = 16;
1321 switch (var->bits_per_pixel) {
1322 case 8:
1323 rc = 256;
1324 break;
1325 case 16:
1326 rc = 16;
1327 break;
1328 case 32:
1329 rc = 16;
1330 break;
1332 return rc;
1335 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1336 unsigned blue, unsigned transp, struct fb_info *info)
1338 if (regno >= XGIfb_get_cmap_len(&info->var))
1339 return 1;
1341 switch (info->var.bits_per_pixel) {
1342 case 8:
1343 outXGIREG(XGIDACA, regno);
1344 outXGIREG(XGIDACD, (red >> 10));
1345 outXGIREG(XGIDACD, (green >> 10));
1346 outXGIREG(XGIDACD, (blue >> 10));
1347 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1348 outXGIREG(XGIDAC2A, regno);
1349 outXGIREG(XGIDAC2D, (red >> 8));
1350 outXGIREG(XGIDAC2D, (green >> 8));
1351 outXGIREG(XGIDAC2D, (blue >> 8));
1353 break;
1354 case 16:
1355 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1356 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1357 >> 11);
1358 break;
1359 case 32:
1360 red >>= 8;
1361 green >>= 8;
1362 blue >>= 8;
1363 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1364 << 8) | (blue);
1365 break;
1367 return 0;
1370 static int XGIfb_set_par(struct fb_info *info)
1372 int err;
1374 /* printk("XGIfb: inside set_par\n"); */
1375 err = XGIfb_do_set_var(&info->var, 1, info);
1376 if (err)
1377 return err;
1378 XGIfb_get_fix(&info->fix, -1, info);
1379 /* printk("XGIfb: end of set_par\n"); */
1380 return 0;
1383 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1385 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1386 + var->hsync_len;
1387 unsigned int vtotal = 0;
1388 unsigned int drate = 0, hrate = 0;
1389 int found_mode = 0;
1390 int refresh_rate, search_idx;
1392 DEBUGPRN("Inside check_var");
1394 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1395 vtotal = var->upper_margin + var->yres + var->lower_margin
1396 + var->vsync_len;
1397 vtotal <<= 1;
1398 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1399 vtotal = var->upper_margin + var->yres + var->lower_margin
1400 + var->vsync_len;
1401 vtotal <<= 2;
1402 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1403 vtotal = var->upper_margin + (var->yres / 2)
1404 + var->lower_margin + var->vsync_len;
1405 } else
1406 vtotal = var->upper_margin + var->yres + var->lower_margin
1407 + var->vsync_len;
1409 if (!(htotal) || !(vtotal))
1410 XGIFAIL("XGIfb: no valid timing data");
1412 if (var->pixclock && htotal && vtotal) {
1413 drate = 1000000000 / var->pixclock;
1414 hrate = (drate * 1000) / htotal;
1415 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1416 printk(KERN_DEBUG
1417 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1418 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1419 __func__, var->pixclock, htotal, vtotal,
1420 __func__, drate, hrate, xgi_video_info.refresh_rate);
1421 } else {
1422 xgi_video_info.refresh_rate = 60;
1426 if ((var->pixclock) && (htotal)) {
1427 drate = 1E12 / var->pixclock;
1428 hrate = drate / htotal;
1429 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1430 } else {
1431 refresh_rate = 60;
1434 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1435 if ((var->xres == 1024) && (var->yres == 600))
1436 refresh_rate = 60;
1438 search_idx = 0;
1439 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1440 (XGIbios_mode[search_idx].xres <= var->xres)) {
1441 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1442 (XGIbios_mode[search_idx].yres == var->yres) &&
1443 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1444 if (XGIfb_validate_mode(search_idx) > 0) {
1445 found_mode = 1;
1446 break;
1449 search_idx++;
1452 if (!found_mode) {
1454 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1455 var->xres, var->yres, var->bits_per_pixel);
1456 search_idx = 0;
1457 while (XGIbios_mode[search_idx].mode_no != 0) {
1459 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1460 (var->yres <= XGIbios_mode[search_idx].yres) &&
1461 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp)) {
1462 if (XGIfb_validate_mode(search_idx) > 0) {
1463 found_mode = 1;
1464 break;
1467 search_idx++;
1469 if (found_mode) {
1470 var->xres = XGIbios_mode[search_idx].xres;
1471 var->yres = XGIbios_mode[search_idx].yres;
1472 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1473 var->xres, var->yres, var->bits_per_pixel);
1475 } else {
1476 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1477 var->xres, var->yres, var->bits_per_pixel);
1478 return -EINVAL;
1482 /* TW: TODO: Check the refresh rate */
1484 /* Adapt RGB settings */
1485 XGIfb_bpp_to_var(var);
1487 /* Sanity check for offsets */
1488 if (var->xoffset < 0)
1489 var->xoffset = 0;
1490 if (var->yoffset < 0)
1491 var->yoffset = 0;
1493 if (!XGIfb_ypan) {
1494 if (var->xres != var->xres_virtual)
1495 var->xres_virtual = var->xres;
1496 if (var->yres != var->yres_virtual)
1497 var->yres_virtual = var->yres;
1498 } /* else { */
1499 /* TW: Now patch yres_virtual if we use panning */
1500 /* May I do this? */
1501 /* var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); */
1502 /* if (var->yres_virtual <= var->yres) { */
1503 /* TW: Paranoia check */
1504 /* var->yres_virtual = var->yres; */
1505 /* } */
1506 /* } */
1508 /* Truncate offsets to maximum if too high */
1509 if (var->xoffset > var->xres_virtual - var->xres)
1510 var->xoffset = var->xres_virtual - var->xres - 1;
1512 if (var->yoffset > var->yres_virtual - var->yres)
1513 var->yoffset = var->yres_virtual - var->yres - 1;
1515 /* Set everything else to 0 */
1516 var->red.msb_right =
1517 var->green.msb_right =
1518 var->blue.msb_right =
1519 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1521 DEBUGPRN("end of check_var");
1522 return 0;
1525 #ifdef XGIFB_PAN
1526 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1527 struct fb_info *info)
1529 int err;
1531 /* printk("\nInside pan_display:\n"); */
1533 if (var->xoffset > (var->xres_virtual - var->xres))
1534 return -EINVAL;
1535 if (var->yoffset > (var->yres_virtual - var->yres))
1536 return -EINVAL;
1538 if (var->vmode & FB_VMODE_YWRAP) {
1539 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1540 || var->xoffset)
1541 return -EINVAL;
1542 } else {
1543 if (var->xoffset + info->var.xres > info->var.xres_virtual
1544 || var->yoffset + info->var.yres
1545 > info->var.yres_virtual)
1546 return -EINVAL;
1548 err = XGIfb_pan_var(var);
1549 if (err < 0)
1550 return err;
1552 info->var.xoffset = var->xoffset;
1553 info->var.yoffset = var->yoffset;
1554 if (var->vmode & FB_VMODE_YWRAP)
1555 info->var.vmode |= FB_VMODE_YWRAP;
1556 else
1557 info->var.vmode &= ~FB_VMODE_YWRAP;
1559 /* printk("End of pan_display\n"); */
1560 return 0;
1562 #endif
1564 static int XGIfb_blank(int blank, struct fb_info *info)
1566 u8 reg;
1568 inXGIIDXREG(XGICR, 0x17, reg);
1570 if (blank > 0)
1571 reg &= 0x7f;
1572 else
1573 reg |= 0x80;
1575 outXGIIDXREG(XGICR, 0x17, reg);
1576 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1577 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1578 return 0;
1581 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1582 unsigned long arg)
1584 DEBUGPRN("inside ioctl");
1585 switch (cmd) {
1586 case FBIO_ALLOC:
1587 if (!capable(CAP_SYS_RAWIO))
1588 return -EPERM;
1589 XGI_malloc((struct XGI_memreq *) arg);
1590 break;
1591 case FBIO_FREE:
1592 if (!capable(CAP_SYS_RAWIO))
1593 return -EPERM;
1594 XGI_free(*(unsigned long *) arg);
1595 break;
1596 case FBIOGET_HWCINFO: {
1597 unsigned long *hwc_offset = (unsigned long *) arg;
1599 if (XGIfb_caps & HW_CURSOR_CAP)
1600 *hwc_offset
1601 = XGIfb_hwcursor_vbase
1602 - (unsigned long) xgi_video_info.video_vbase;
1603 else
1604 *hwc_offset = 0;
1606 break;
1608 case FBIOPUT_MODEINFO: {
1609 struct mode_info *x = (struct mode_info *) arg;
1611 xgi_video_info.video_bpp = x->bpp;
1612 xgi_video_info.video_width = x->xres;
1613 xgi_video_info.video_height = x->yres;
1614 xgi_video_info.video_vwidth = x->v_xres;
1615 xgi_video_info.video_vheight = x->v_yres;
1616 xgi_video_info.org_x = x->org_x;
1617 xgi_video_info.org_y = x->org_y;
1618 xgi_video_info.refresh_rate = x->vrate;
1619 xgi_video_info.video_linelength = xgi_video_info.video_vwidth
1620 * (xgi_video_info.video_bpp >> 3);
1621 switch (xgi_video_info.video_bpp) {
1622 case 8:
1623 xgi_video_info.DstColor = 0x0000;
1624 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1625 xgi_video_info.video_cmap_len = 256;
1626 break;
1627 case 16:
1628 xgi_video_info.DstColor = 0x8000;
1629 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1630 xgi_video_info.video_cmap_len = 16;
1631 break;
1632 case 32:
1633 xgi_video_info.DstColor = 0xC000;
1634 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1635 xgi_video_info.video_cmap_len = 16;
1636 break;
1637 default:
1638 xgi_video_info.video_cmap_len = 16;
1639 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1640 xgi_video_info.accel = 0;
1641 break;
1644 break;
1646 case FBIOGET_DISPINFO:
1647 XGI_dispinfo((struct ap_data *) arg);
1648 break;
1649 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1651 struct XGIfb_info *x = (struct XGIfb_info *) arg;
1653 /* x->XGIfb_id = XGIFB_ID; */
1654 x->XGIfb_version = VER_MAJOR;
1655 x->XGIfb_revision = VER_MINOR;
1656 x->XGIfb_patchlevel = VER_LEVEL;
1657 x->chip_id = xgi_video_info.chip_id;
1658 x->memory = xgi_video_info.video_size / 1024;
1659 x->heapstart = xgi_video_info.heapstart / 1024;
1660 x->fbvidmode = XGIfb_mode_no;
1661 x->XGIfb_caps = XGIfb_caps;
1662 x->XGIfb_tqlen = 512; /* yet unused */
1663 x->XGIfb_pcibus = xgi_video_info.pcibus;
1664 x->XGIfb_pcislot = xgi_video_info.pcislot;
1665 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1666 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1667 x->XGIfb_lcda = XGIfb_detectedlcda;
1668 break;
1670 case XGIFB_GET_VBRSTATUS: {
1671 unsigned long *vbrstatus = (unsigned long *) arg;
1672 if (XGIfb_CheckVBRetrace())
1673 *vbrstatus = 1;
1674 else
1675 *vbrstatus = 0;
1677 default:
1678 return -EINVAL;
1679 } DEBUGPRN("end of ioctl");
1680 return 0;
1684 /* ----------- FBDev related routines for all series ---------- */
1686 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1687 struct fb_info *info)
1689 DEBUGPRN("inside get_fix");
1690 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1692 strcpy(fix->id, myid);
1694 fix->smem_start = xgi_video_info.video_base;
1696 fix->smem_len = xgi_video_info.video_size;
1698 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1699 if (xgi_video_info.video_size > 0x1000000) {
1700 fix->smem_len = 0xD00000;
1701 } else if (xgi_video_info.video_size > 0x800000)
1702 fix->smem_len = 0x800000;
1703 else
1704 fix->smem_len = 0x400000;
1705 } else
1706 fix->smem_len = XGIfb_mem * 1024;
1708 fix->type = video_type;
1709 fix->type_aux = 0;
1710 if (xgi_video_info.video_bpp == 8)
1711 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1712 else
1713 fix->visual = FB_VISUAL_DIRECTCOLOR;
1714 fix->xpanstep = 0;
1715 #ifdef XGIFB_PAN
1716 if (XGIfb_ypan)
1717 fix->ypanstep = 1;
1718 #endif
1719 fix->ywrapstep = 0;
1720 fix->line_length = xgi_video_info.video_linelength;
1721 fix->mmio_start = xgi_video_info.mmio_base;
1722 fix->mmio_len = XGIfb_mmio_size;
1723 if (xgi_video_info.chip >= XG40)
1724 fix->accel = FB_ACCEL_XGI_XABRE;
1725 else
1726 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1728 DEBUGPRN("end of get_fix");
1729 return 0;
1732 static struct fb_ops XGIfb_ops = {
1733 .owner = THIS_MODULE,
1734 .fb_open = XGIfb_open,
1735 .fb_release = XGIfb_release,
1736 .fb_check_var = XGIfb_check_var,
1737 .fb_set_par = XGIfb_set_par,
1738 .fb_setcolreg = XGIfb_setcolreg,
1739 #ifdef XGIFB_PAN
1740 .fb_pan_display = XGIfb_pan_display,
1741 #endif
1742 .fb_blank = XGIfb_blank,
1743 .fb_fillrect = fbcon_XGI_fillrect,
1744 .fb_copyarea = fbcon_XGI_copyarea,
1745 .fb_imageblit = cfb_imageblit,
1746 .fb_sync = fbcon_XGI_sync,
1747 .fb_ioctl = XGIfb_ioctl,
1748 /* .fb_mmap = XGIfb_mmap, */
1751 /* ---------------- Chip generation dependent routines ---------------- */
1753 /* for XGI 315/550/650/740/330 */
1755 static int XGIfb_get_dram_size(void)
1758 u8 ChannelNum, tmp;
1759 u8 reg = 0;
1761 /* xorg driver sets 32MB * 1 channel */
1762 if (xgi_video_info.chip == XG27)
1763 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1765 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1766 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1767 case XGI_DRAM_SIZE_1MB:
1768 xgi_video_info.video_size = 0x100000;
1769 break;
1770 case XGI_DRAM_SIZE_2MB:
1771 xgi_video_info.video_size = 0x200000;
1772 break;
1773 case XGI_DRAM_SIZE_4MB:
1774 xgi_video_info.video_size = 0x400000;
1775 break;
1776 case XGI_DRAM_SIZE_8MB:
1777 xgi_video_info.video_size = 0x800000;
1778 break;
1779 case XGI_DRAM_SIZE_16MB:
1780 xgi_video_info.video_size = 0x1000000;
1781 break;
1782 case XGI_DRAM_SIZE_32MB:
1783 xgi_video_info.video_size = 0x2000000;
1784 break;
1785 case XGI_DRAM_SIZE_64MB:
1786 xgi_video_info.video_size = 0x4000000;
1787 break;
1788 case XGI_DRAM_SIZE_128MB:
1789 xgi_video_info.video_size = 0x8000000;
1790 break;
1791 case XGI_DRAM_SIZE_256MB:
1792 xgi_video_info.video_size = 0x10000000;
1793 break;
1794 default:
1795 return -1;
1798 tmp = (reg & 0x0c) >> 2;
1799 switch (xgi_video_info.chip) {
1800 case XG20:
1801 case XG21:
1802 case XG27:
1803 ChannelNum = 1;
1804 break;
1806 case XG42:
1807 if (reg & 0x04)
1808 ChannelNum = 2;
1809 else
1810 ChannelNum = 1;
1811 break;
1813 case XG45:
1814 if (tmp == 1)
1815 ChannelNum = 2;
1816 else if (tmp == 2)
1817 ChannelNum = 3;
1818 else if (tmp == 3)
1819 ChannelNum = 4;
1820 else
1821 ChannelNum = 1;
1822 break;
1824 case XG40:
1825 default:
1826 if (tmp == 2)
1827 ChannelNum = 2;
1828 else if (tmp == 3)
1829 ChannelNum = 3;
1830 else
1831 ChannelNum = 1;
1832 break;
1835 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1836 /* PLiad fixed for benchmarking and fb set */
1837 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1838 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1840 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", reg,
1841 xgi_video_info.video_size, ChannelNum);
1842 return 0;
1846 static void XGIfb_detect_VB(void)
1848 u8 cr32, temp = 0;
1850 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1852 switch (xgi_video_info.hasVB) {
1853 case HASVB_LVDS_CHRONTEL:
1854 case HASVB_CHRONTEL:
1855 break;
1856 case HASVB_301:
1857 case HASVB_302:
1858 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1859 break;
1862 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1864 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1865 XGIfb_crt1off = 0;
1866 else {
1867 if (cr32 & 0x5F)
1868 XGIfb_crt1off = 1;
1869 else
1870 XGIfb_crt1off = 0;
1873 if (XGIfb_crt2type != -1)
1874 /* TW: Override with option */
1875 xgi_video_info.disp_state = XGIfb_crt2type;
1876 else if (cr32 & XGI_VB_TV)
1877 xgi_video_info.disp_state = DISPTYPE_TV;
1878 else if (cr32 & XGI_VB_LCD)
1879 xgi_video_info.disp_state = DISPTYPE_LCD;
1880 else if (cr32 & XGI_VB_CRT2)
1881 xgi_video_info.disp_state = DISPTYPE_CRT2;
1882 else
1883 xgi_video_info.disp_state = 0;
1885 if (XGIfb_tvplug != -1)
1886 /* PR/TW: Override with option */
1887 xgi_video_info.TV_plug = XGIfb_tvplug;
1888 else if (cr32 & XGI_VB_HIVISION) {
1889 xgi_video_info.TV_type = TVMODE_HIVISION;
1890 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1891 } else if (cr32 & XGI_VB_SVIDEO)
1892 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1893 else if (cr32 & XGI_VB_COMPOSITE)
1894 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1895 else if (cr32 & XGI_VB_SCART)
1896 xgi_video_info.TV_plug = TVPLUG_SCART;
1898 if (xgi_video_info.TV_type == 0) {
1899 /* TW: PAL/NTSC changed for 650 */
1900 if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
1901 >= XGI_330)) {
1903 inXGIIDXREG(XGICR, 0x38, temp);
1904 if (temp & 0x10)
1905 xgi_video_info.TV_type = TVMODE_PAL;
1906 else
1907 xgi_video_info.TV_type = TVMODE_NTSC;
1909 } else {
1911 inXGIIDXREG(XGICR, 0x79, temp);
1912 if (temp & 0x20)
1913 xgi_video_info.TV_type = TVMODE_PAL;
1914 else
1915 xgi_video_info.TV_type = TVMODE_NTSC;
1919 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1920 if (XGIfb_forcecrt1 != -1) {
1921 if (XGIfb_forcecrt1)
1922 XGIfb_crt1off = 0;
1923 else
1924 XGIfb_crt1off = 1;
1928 static void XGIfb_get_VB_type(void)
1930 u8 reg;
1932 if (!XGIfb_has_VB()) {
1933 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1934 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1935 case XGI310_EXTERNAL_CHIP_LVDS:
1936 xgi_video_info.hasVB = HASVB_LVDS;
1937 break;
1938 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1939 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1940 break;
1941 default:
1942 break;
1947 static int XGIfb_has_VB(void)
1949 u8 vb_chipid;
1951 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1952 switch (vb_chipid) {
1953 case 0x01:
1954 xgi_video_info.hasVB = HASVB_301;
1955 break;
1956 case 0x02:
1957 xgi_video_info.hasVB = HASVB_302;
1958 break;
1959 default:
1960 xgi_video_info.hasVB = HASVB_NONE;
1961 return 0;
1963 return 1;
1966 /* ------------------ Sensing routines ------------------ */
1968 /* TW: Determine and detect attached devices on XGI30x */
1969 int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1971 int temp, i;
1973 outXGIIDXREG(XGIPART4, 0x11, tempbl);
1974 temp = tempbh | tempcl;
1975 setXGIIDXREG(XGIPART4, 0x10, 0xe0, temp);
1976 for (i = 0; i < 10; i++)
1977 XGI_LongWait(&XGI_Pr);
1978 tempch &= 0x7f;
1979 inXGIIDXREG(XGIPART4, 0x03, temp);
1980 temp ^= 0x0e;
1981 temp &= tempch;
1982 return temp;
1985 void XGI_Sense30x(void)
1987 u8 backupP4_0d;
1988 u8 testsvhs_tempbl, testsvhs_tempbh;
1989 u8 testsvhs_tempcl, testsvhs_tempch;
1990 u8 testcvbs_tempbl, testcvbs_tempbh;
1991 u8 testcvbs_tempcl, testcvbs_tempch;
1992 u8 testvga2_tempbl, testvga2_tempbh;
1993 u8 testvga2_tempcl, testvga2_tempch;
1994 int myflag, result;
1996 inXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
1997 outXGIIDXREG(XGIPART4, 0x0d, (backupP4_0d | 0x04));
1999 testvga2_tempbh = 0x00;
2000 testvga2_tempbl = 0xd1;
2001 testsvhs_tempbh = 0x00;
2002 testsvhs_tempbl = 0xb9;
2003 testcvbs_tempbh = 0x00;
2004 testcvbs_tempbl = 0xb3;
2005 if ((XGIhw_ext.ujVBChipID != VB_CHIP_301) && (XGIhw_ext.ujVBChipID
2006 != VB_CHIP_302)) {
2007 testvga2_tempbh = 0x01;
2008 testvga2_tempbl = 0x90;
2009 testsvhs_tempbh = 0x01;
2010 testsvhs_tempbl = 0x6b;
2011 testcvbs_tempbh = 0x01;
2012 testcvbs_tempbl = 0x74;
2013 if (XGIhw_ext.ujVBChipID == VB_CHIP_301LV
2014 || XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2015 testvga2_tempbh = 0x00;
2016 testvga2_tempbl = 0x00;
2017 testsvhs_tempbh = 0x02;
2018 testsvhs_tempbl = 0x00;
2019 testcvbs_tempbh = 0x01;
2020 testcvbs_tempbl = 0x00;
2023 if (XGIhw_ext.ujVBChipID != VB_CHIP_301LV && XGIhw_ext.ujVBChipID
2024 != VB_CHIP_302LV) {
2025 inXGIIDXREG(XGIPART4, 0x01, myflag);
2026 if (myflag & 0x04) {
2027 testvga2_tempbh = 0x00;
2028 testvga2_tempbl = 0xfd;
2029 testsvhs_tempbh = 0x00;
2030 testsvhs_tempbl = 0xdd;
2031 testcvbs_tempbh = 0x00;
2032 testcvbs_tempbl = 0xee;
2035 if ((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || (XGIhw_ext.ujVBChipID
2036 == VB_CHIP_302LV)) {
2037 testvga2_tempbh = 0x00;
2038 testvga2_tempbl = 0x00;
2039 testvga2_tempch = 0x00;
2040 testvga2_tempcl = 0x00;
2041 testsvhs_tempch = 0x04;
2042 testsvhs_tempcl = 0x08;
2043 testcvbs_tempch = 0x08;
2044 testcvbs_tempcl = 0x08;
2045 } else {
2046 testvga2_tempch = 0x0e;
2047 testvga2_tempcl = 0x08;
2048 testsvhs_tempch = 0x06;
2049 testsvhs_tempcl = 0x04;
2050 testcvbs_tempch = 0x08;
2051 testcvbs_tempcl = 0x04;
2054 if (testvga2_tempch || testvga2_tempcl || testvga2_tempbh
2055 || testvga2_tempbl) {
2056 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2057 testvga2_tempcl, testvga2_tempch);
2058 if (result) {
2059 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2060 orXGIIDXREG(XGICR, 0x32, 0x10);
2064 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, testsvhs_tempcl,
2065 testsvhs_tempch);
2066 if (result) {
2067 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2068 /* TW: So we can be sure that there IS a SVHS output */
2069 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2070 orXGIIDXREG(XGICR, 0x32, 0x02);
2073 if (!result) {
2074 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2075 testcvbs_tempcl, testcvbs_tempch);
2076 if (result) {
2077 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2078 /* TW: So we can be sure that there IS a CVBS output */
2079 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2080 orXGIIDXREG(XGICR, 0x32, 0x01);
2083 XGIDoSense(0, 0, 0, 0);
2085 outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
2088 /* ------------------------ Heap routines -------------------------- */
2090 static int XGIfb_heap_init(void)
2092 XGI_OH *poh;
2093 u8 temp = 0;
2095 int agp_enabled = 1;
2096 u32 agp_size;
2097 unsigned long *cmdq_baseport = NULL;
2098 unsigned long *read_port = NULL;
2099 unsigned long *write_port = NULL;
2100 XGI_CMDTYPE cmd_type;
2101 #ifndef AGPOFF
2102 struct agp_kern_info *agp_info;
2103 struct agp_memory *agp;
2104 u32 agp_phys;
2105 #endif
2107 /* TW: The heap start is either set manually using the "mem" parameter, or
2108 * defaults as follows:
2109 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2110 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2111 * -) If 4MB or less is available, let it start at 4MB.
2112 * This is for avoiding a clash with X driver which uses the beginning
2113 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2114 * in XF86Config-4.
2115 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2116 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2118 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
2119 if (xgi_video_info.video_size > 0x1000000)
2120 xgi_video_info.heapstart = 0xD00000;
2121 else if (xgi_video_info.video_size > 0x800000)
2122 xgi_video_info.heapstart = 0x800000;
2123 else
2124 xgi_video_info.heapstart = 0x400000;
2125 } else {
2126 xgi_video_info.heapstart = XGIfb_mem * 1024;
2128 XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
2129 + xgi_video_info.heapstart);
2130 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2131 (int)(xgi_video_info.heapstart / 1024));
2133 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
2134 + xgi_video_info.video_size;
2135 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2137 /* TW: Now initialize the 310 series' command queue mode.
2138 * On 310/325, there are three queue modes available which
2139 * are chosen by setting bits 7:5 in SR26:
2140 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2141 * track of the queue, the FIFO, command parsing and so
2142 * on. This is the one comparable to the 300 series.
2143 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2144 * have to do queue management himself. Register 0x85c4 will
2145 * hold the location of the next free queue slot, 0x85c8
2146 * is the "queue read pointer" whose way of working is
2147 * unknown to me. Anyway, this mode would require a
2148 * translation of the MMIO commands to some kind of
2149 * accelerator assembly and writing these commands
2150 * to the memory location pointed to by 0x85c4.
2151 * We will not use this, as nobody knows how this
2152 * "assembly" works, and as it would require a complete
2153 * re-write of the accelerator code.
2154 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2155 * queue in AGP memory space.
2157 * SR26 bit 4 is called "Bypass H/W queue".
2158 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2159 * SR26 bit 0 resets the queue
2160 * Size of queue memory is encoded in bits 3:2 like this:
2161 * 00 (0x00) 512K
2162 * 01 (0x04) 1M
2163 * 10 (0x08) 2M
2164 * 11 (0x0C) 4M
2165 * The queue location is to be written to 0x85C0.
2168 cmdq_baseport = (unsigned long *) (xgi_video_info.mmio_vbase
2169 + MMIO_QUEUE_PHYBASE);
2170 write_port = (unsigned long *) (xgi_video_info.mmio_vbase
2171 + MMIO_QUEUE_WRITEPORT);
2172 read_port = (unsigned long *) (xgi_video_info.mmio_vbase
2173 + MMIO_QUEUE_READPORT);
2175 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2177 agp_size = COMMAND_QUEUE_AREA_SIZE;
2179 #ifndef AGPOFF
2180 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2181 agp_info = vmalloc(sizeof(*agp_info));
2182 memset((void *)agp_info, 0x00, sizeof(*agp_info));
2183 agp_copy_info(agp_info);
2185 agp_backend_acquire();
2187 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
2188 AGP_NORMAL_MEMORY);
2189 if (agp == NULL) {
2190 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2191 agp_enabled = 0;
2192 } else {
2193 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2194 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2195 /* TODO: Free AGP memory here */
2196 agp_enabled = 0;
2197 } else {
2198 agp_enable(0);
2202 #else
2203 agp_enabled = 0;
2204 #endif
2206 /* TW: Now select the queue mode */
2208 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2209 cmd_type = AGP_CMD_QUEUE;
2210 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2211 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2212 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2213 cmd_type = VM_CMD_QUEUE;
2214 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2215 } else {
2216 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2217 cmd_type = MMIO_CMD;
2220 switch (agp_size) {
2221 case 0x80000:
2222 temp = XGI_CMD_QUEUE_SIZE_512k;
2223 break;
2224 case 0x100000:
2225 temp = XGI_CMD_QUEUE_SIZE_1M;
2226 break;
2227 case 0x200000:
2228 temp = XGI_CMD_QUEUE_SIZE_2M;
2229 break;
2230 case 0x400000:
2231 temp = XGI_CMD_QUEUE_SIZE_4M;
2232 break;
2235 switch (cmd_type) {
2236 case AGP_CMD_QUEUE:
2237 #ifndef AGPOFF
2238 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2239 agp_info->aper_base, agp->physical, agp_size/1024);
2241 agp_phys = agp_info->aper_base + agp->physical;
2243 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2244 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2246 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2248 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2250 *write_port = *read_port;
2252 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2253 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2255 *cmdq_baseport = agp_phys;
2257 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2258 #endif
2259 break;
2261 case VM_CMD_QUEUE:
2262 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2263 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2265 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2267 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2269 *write_port = *read_port;
2271 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2272 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2274 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2276 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2278 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2279 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2280 break;
2282 default: /* MMIO */
2284 /* printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); */
2285 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2286 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2287 * enough. Reserve memory in any way.
2289 /* FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; */
2290 /* FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; */
2291 /* FIXME */
2292 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); */
2293 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); */
2294 /* FIXME */
2295 /* FIXME *write_port = *read_port; */
2296 /* FIXME */
2297 /* FIXME *//* TW: Set Auto_Correction bit */
2298 /* FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); */
2299 /* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); */
2300 /* FIXME */
2301 /* FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; */
2302 /* FIXME */
2303 /* FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; */
2304 /* FIXME */
2305 /* FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", */
2306 /* FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); */
2307 break;
2310 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2311 top of the videoRAM, right below the TB memory area (if used). */
2312 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2313 XGIfb_heap_end -= XGIfb_hwcursor_size;
2314 XGIfb_heap_size -= XGIfb_hwcursor_size;
2315 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2317 XGIfb_caps |= HW_CURSOR_CAP;
2319 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2320 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2323 XGIfb_heap.poha_chain = NULL;
2324 XGIfb_heap.poh_freelist = NULL;
2326 poh = XGIfb_poh_new_node();
2328 if (poh == NULL)
2329 return 1;
2331 poh->poh_next = &XGIfb_heap.oh_free;
2332 poh->poh_prev = &XGIfb_heap.oh_free;
2333 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2334 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2336 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2337 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2338 (unsigned int) poh->size / 1024);
2340 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2341 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2343 XGIfb_heap.oh_free.poh_next = poh;
2344 XGIfb_heap.oh_free.poh_prev = poh;
2345 XGIfb_heap.oh_free.size = 0;
2346 XGIfb_heap.max_freesize = poh->size;
2348 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2349 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2350 XGIfb_heap.oh_used.size = SENTINEL;
2352 return 0;
2355 static XGI_OH *XGIfb_poh_new_node(void)
2357 int i;
2358 unsigned long cOhs;
2359 XGI_OHALLOC *poha;
2360 XGI_OH *poh;
2362 if (XGIfb_heap.poh_freelist == NULL) {
2363 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2364 if (!poha)
2365 return NULL;
2367 poha->poha_next = XGIfb_heap.poha_chain;
2368 XGIfb_heap.poha_chain = poha;
2370 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
2371 + 1;
2373 poh = &poha->aoh[0];
2374 for (i = cOhs - 1; i != 0; i--) {
2375 poh->poh_next = poh + 1;
2376 poh = poh + 1;
2379 poh->poh_next = NULL;
2380 XGIfb_heap.poh_freelist = &poha->aoh[0];
2383 poh = XGIfb_heap.poh_freelist;
2384 XGIfb_heap.poh_freelist = poh->poh_next;
2386 return poh;
2389 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2391 XGI_OH *pohThis;
2392 XGI_OH *pohRoot;
2393 int bAllocated = 0;
2395 if (size > XGIfb_heap.max_freesize) {
2396 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2397 (unsigned int) size / 1024);
2398 return NULL;
2401 pohThis = XGIfb_heap.oh_free.poh_next;
2403 while (pohThis != &XGIfb_heap.oh_free) {
2404 if (size <= pohThis->size) {
2405 bAllocated = 1;
2406 break;
2408 pohThis = pohThis->poh_next;
2411 if (!bAllocated) {
2412 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2413 (unsigned int) size / 1024);
2414 return NULL;
2417 if (size == pohThis->size) {
2418 pohRoot = pohThis;
2419 XGIfb_delete_node(pohThis);
2420 } else {
2421 pohRoot = XGIfb_poh_new_node();
2423 if (pohRoot == NULL)
2424 return NULL;
2426 pohRoot->offset = pohThis->offset;
2427 pohRoot->size = size;
2429 pohThis->offset += size;
2430 pohThis->size -= size;
2433 XGIfb_heap.max_freesize -= size;
2435 pohThis = &XGIfb_heap.oh_used;
2436 XGIfb_insert_node(pohThis, pohRoot);
2438 return pohRoot;
2441 static void XGIfb_delete_node(XGI_OH *poh)
2443 XGI_OH *poh_prev;
2444 XGI_OH *poh_next;
2446 poh_prev = poh->poh_prev;
2447 poh_next = poh->poh_next;
2449 poh_prev->poh_next = poh_next;
2450 poh_next->poh_prev = poh_prev;
2454 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2456 XGI_OH *pohTemp;
2458 pohTemp = pohList->poh_next;
2460 pohList->poh_next = poh;
2461 pohTemp->poh_prev = poh;
2463 poh->poh_prev = pohList;
2464 poh->poh_next = pohTemp;
2467 static XGI_OH *XGIfb_poh_free(unsigned long base)
2469 XGI_OH *pohThis;
2470 XGI_OH *poh_freed;
2471 XGI_OH *poh_prev;
2472 XGI_OH *poh_next;
2473 unsigned long ulUpper;
2474 unsigned long ulLower;
2475 int foundNode = 0;
2477 poh_freed = XGIfb_heap.oh_used.poh_next;
2479 while (poh_freed != &XGIfb_heap.oh_used) {
2480 if (poh_freed->offset == base) {
2481 foundNode = 1;
2482 break;
2485 poh_freed = poh_freed->poh_next;
2488 if (!foundNode)
2489 return NULL;
2491 XGIfb_heap.max_freesize += poh_freed->size;
2493 poh_prev = poh_next = NULL;
2494 ulUpper = poh_freed->offset + poh_freed->size;
2495 ulLower = poh_freed->offset;
2497 pohThis = XGIfb_heap.oh_free.poh_next;
2499 while (pohThis != &XGIfb_heap.oh_free) {
2500 if (pohThis->offset == ulUpper)
2501 poh_next = pohThis;
2502 else if ((pohThis->offset + pohThis->size) == ulLower)
2503 poh_prev = pohThis;
2505 pohThis = pohThis->poh_next;
2508 XGIfb_delete_node(poh_freed);
2510 if (poh_prev && poh_next) {
2511 poh_prev->size += (poh_freed->size + poh_next->size);
2512 XGIfb_delete_node(poh_next);
2513 XGIfb_free_node(poh_freed);
2514 XGIfb_free_node(poh_next);
2515 return poh_prev;
2518 if (poh_prev) {
2519 poh_prev->size += poh_freed->size;
2520 XGIfb_free_node(poh_freed);
2521 return poh_prev;
2524 if (poh_next) {
2525 poh_next->size += poh_freed->size;
2526 poh_next->offset = poh_freed->offset;
2527 XGIfb_free_node(poh_freed);
2528 return poh_next;
2531 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2533 return poh_freed;
2536 static void XGIfb_free_node(XGI_OH *poh)
2538 if (poh == NULL)
2539 return;
2541 poh->poh_next = XGIfb_heap.poh_freelist;
2542 XGIfb_heap.poh_freelist = poh;
2546 void XGI_malloc(struct XGI_memreq *req)
2548 XGI_OH *poh;
2550 poh = XGIfb_poh_allocate(req->size);
2552 if (poh == NULL) {
2553 req->offset = 0;
2554 req->size = 0;
2555 DPRINTK("XGIfb: Video RAM allocation failed\n");
2556 } else {
2557 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2558 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2560 req->offset = poh->offset;
2561 req->size = poh->size;
2566 void XGI_free(unsigned long base)
2568 XGI_OH *poh;
2570 poh = XGIfb_poh_free(base);
2572 if (poh == NULL) {
2573 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2574 (unsigned int) base);
2578 /* --------------------- SetMode routines ------------------------- */
2580 static void XGIfb_pre_setmode(void)
2582 u8 cr30 = 0, cr31 = 0;
2584 inXGIIDXREG(XGICR, 0x31, cr31);
2585 cr31 &= ~0x60;
2587 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2588 case DISPTYPE_CRT2:
2589 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2590 cr31 |= XGI_DRIVER_MODE;
2591 break;
2592 case DISPTYPE_LCD:
2593 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2594 cr31 |= XGI_DRIVER_MODE;
2595 break;
2596 case DISPTYPE_TV:
2597 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2598 cr30 = (XGI_VB_OUTPUT_HIVISION
2599 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2600 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2601 cr30 = (XGI_VB_OUTPUT_SVIDEO
2602 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2603 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2604 cr30 = (XGI_VB_OUTPUT_COMPOSITE
2605 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2606 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2607 cr30 = (XGI_VB_OUTPUT_SCART
2608 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2609 cr31 |= XGI_DRIVER_MODE;
2611 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2612 cr31 |= 0x01;
2613 else
2614 cr31 &= ~0x01;
2615 break;
2616 default: /* disable CRT2 */
2617 cr30 = 0x00;
2618 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2621 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2622 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2623 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2625 if (xgi_video_info.accel)
2626 XGIfb_syncaccel();
2630 static void XGIfb_post_setmode(void)
2632 u8 reg;
2633 unsigned char doit = 1;
2635 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2636 outXGIIDXREG(XGICR, 0x13, 0x00);
2637 setXGIIDXREG(XGISR,0x0E, 0xF0, 0x01);
2638 *test*
2640 if (xgi_video_info.video_bpp == 8) {
2641 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2642 if ((xgi_video_info.hasVB == HASVB_LVDS)
2643 || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2644 doit = 0;
2646 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2647 if (xgi_video_info.disp_state & DISPTYPE_LCD)
2648 doit = 0;
2651 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2652 if (xgi_video_info.hasVB != HASVB_NONE) {
2653 inXGIIDXREG(XGIPART1, 0x00, reg);
2655 if ((reg & 0x50) == 0x10)
2656 doit = 0;
2658 } else {
2659 XGIfb_crt1off = 0;
2662 inXGIIDXREG(XGICR, 0x17, reg);
2663 if ((XGIfb_crt1off) && (doit))
2664 reg &= ~0x80;
2665 else
2666 reg |= 0x80;
2667 outXGIIDXREG(XGICR, 0x17, reg);
2669 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2671 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
2672 == HASVB_301)) {
2674 inXGIIDXREG(XGIPART4, 0x01, reg);
2676 if (reg < 0xB0) { /* Set filter for XGI301 */
2678 switch (xgi_video_info.video_width) {
2679 case 320:
2680 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2681 break;
2682 case 640:
2683 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2684 break;
2685 case 720:
2686 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2687 break;
2688 case 800:
2689 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2690 break;
2691 default:
2692 filter = -1;
2693 break;
2696 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2698 if (xgi_video_info.TV_type == TVMODE_NTSC) {
2700 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2702 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2704 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2706 } else if (xgi_video_info.TV_plug
2707 == TVPLUG_COMPOSITE) {
2709 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2711 switch (xgi_video_info.video_width) {
2712 case 640:
2713 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2714 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2715 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2716 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2717 break;
2718 case 720:
2719 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2720 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2721 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2722 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2723 break;
2724 case 800:
2725 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2726 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2727 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2728 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2729 break;
2733 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
2735 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2737 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2739 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2741 } else if (xgi_video_info.TV_plug
2742 == TVPLUG_COMPOSITE) {
2744 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2746 switch (xgi_video_info.video_width) {
2747 case 640:
2748 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2749 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2750 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2751 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2752 break;
2753 case 720:
2754 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2755 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2756 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2757 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2758 break;
2759 case 800:
2760 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2761 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2762 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2763 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2764 break;
2769 if ((filter >= 0) && (filter <= 7)) {
2770 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2771 XGI_TV_filter[filter_tb].filter[filter][0],
2772 XGI_TV_filter[filter_tb].filter[filter][1],
2773 XGI_TV_filter[filter_tb].filter[filter][2],
2774 XGI_TV_filter[filter_tb].filter[filter][3]
2776 outXGIIDXREG(
2777 XGIPART2,
2778 0x35,
2779 (XGI_TV_filter[filter_tb].filter[filter][0]));
2780 outXGIIDXREG(
2781 XGIPART2,
2782 0x36,
2783 (XGI_TV_filter[filter_tb].filter[filter][1]));
2784 outXGIIDXREG(
2785 XGIPART2,
2786 0x37,
2787 (XGI_TV_filter[filter_tb].filter[filter][2]));
2788 outXGIIDXREG(
2789 XGIPART2,
2790 0x38,
2791 (XGI_TV_filter[filter_tb].filter[filter][3]));
2800 XGIINITSTATIC int __init XGIfb_setup(char *options)
2802 char *this_opt;
2804 xgi_video_info.refresh_rate = 0;
2806 printk(KERN_INFO "XGIfb: Options %s\n", options);
2808 if (!options || !*options)
2809 return 0;
2811 while ((this_opt = strsep(&options, ",")) != NULL) {
2813 if (!*this_opt)
2814 continue;
2816 if (!strncmp(this_opt, "mode:", 5)) {
2817 XGIfb_search_mode(this_opt + 5);
2818 } else if (!strncmp(this_opt, "vesa:", 5)) {
2819 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2820 } else if (!strncmp(this_opt, "mode:", 5)) {
2821 XGIfb_search_mode(this_opt + 5);
2822 } else if (!strncmp(this_opt, "vesa:", 5)) {
2823 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2824 } else if (!strncmp(this_opt, "vrate:", 6)) {
2825 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2826 } else if (!strncmp(this_opt, "rate:", 5)) {
2827 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2828 } else if (!strncmp(this_opt, "off", 3)) {
2829 XGIfb_off = 1;
2830 } else if (!strncmp(this_opt, "crt1off", 7)) {
2831 XGIfb_crt1off = 1;
2832 } else if (!strncmp(this_opt, "filter:", 7)) {
2833 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2834 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2835 XGIfb_search_crt2type(this_opt + 14);
2836 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2837 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2838 } else if (!strncmp(this_opt, "tvmode:", 7)) {
2839 XGIfb_search_tvstd(this_opt + 7);
2840 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
2841 XGIfb_search_tvstd(this_opt + 7);
2842 } else if (!strncmp(this_opt, "mem:", 4)) {
2843 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2844 } else if (!strncmp(this_opt, "dstn", 4)) {
2845 enable_dstn = 1;
2846 /* TW: DSTN overrules forcecrt2type */
2847 XGIfb_crt2type = DISPTYPE_LCD;
2848 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2849 XGIfb_search_queuemode(this_opt + 10);
2850 } else if (!strncmp(this_opt, "pdc:", 4)) {
2851 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2852 if (XGIfb_pdc & ~0x3c) {
2853 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2854 XGIfb_pdc = 0;
2856 } else if (!strncmp(this_opt, "noaccel", 7)) {
2857 XGIfb_accel = 0;
2858 } else if (!strncmp(this_opt, "noypan", 6)) {
2859 XGIfb_ypan = 0;
2860 } else if (!strncmp(this_opt, "userom:", 7)) {
2861 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2862 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2863 /* XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); */
2864 } else {
2865 XGIfb_search_mode(this_opt);
2866 /* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
2869 /* TW: Acceleration only with MMIO mode */
2870 if ((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2871 XGIfb_ypan = 0;
2872 XGIfb_accel = 0;
2874 /* TW: Panning only with acceleration */
2875 if (XGIfb_accel == 0)
2876 XGIfb_ypan = 0;
2879 printk("\nxgifb: outa xgifb_setup 3450");
2880 return 0;
2883 static unsigned char VBIOS_BUF[65535];
2885 static unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
2887 u32 rom_size = 0;
2888 u32 rom_address = 0;
2889 int j;
2891 /* Get the size of the expansion rom */
2892 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2893 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2894 if ((rom_size & 0x01) == 0) {
2895 printk("No ROM\n");
2896 return NULL;
2899 rom_size &= 0xFFFFF800;
2900 rom_size = (~rom_size) + 1;
2902 rom_address = pci_resource_start(dev, 0);
2903 if (rom_address == 0 || rom_address == 0xFFFFFFF0) {
2904 printk("No suitable rom address found\n");
2905 return NULL;
2908 printk("ROM Size is %dK, Address is %x\n", rom_size / 1024, rom_address);
2910 /* Map ROM */
2911 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address
2912 | PCI_ROM_ADDRESS_ENABLE);
2914 /* memcpy(copy_address, rom_address, rom_size); */
2916 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2918 unsigned char *from = (unsigned char *) virt_addr;
2919 unsigned char *to = (unsigned char *) copy_address;
2920 for (j = 0; j < 65536 /*rom_size*/; j++)
2921 *to++ = *from++;
2924 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2926 printk("Copy is done\n");
2928 return copy_address;
2931 static int __devinit xgifb_probe(struct pci_dev *pdev,
2932 const struct pci_device_id *ent)
2934 u16 reg16;
2935 u8 reg, reg1;
2936 u8 CR48, CR38;
2937 if (XGIfb_off)
2938 return -ENXIO;
2940 XGIfb_registered = 0;
2942 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2943 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2944 if (!fb_info)
2945 return -ENOMEM;
2947 xgi_video_info.chip_id = pdev->device;
2948 pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
2949 pci_read_config_word(pdev, PCI_COMMAND, &reg16);
2950 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2951 XGIvga_enabled = reg16 & 0x01;
2953 xgi_video_info.pcibus = pdev->bus->number;
2954 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2955 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2956 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2957 xgi_video_info.subsysdevice = pdev->subsystem_device;
2959 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2960 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2961 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2962 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2963 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2964 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2965 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2966 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2968 if (pci_enable_device(pdev))
2969 return -EIO;
2971 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2973 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2974 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2976 if (reg1 != 0xa1) { /*I/O error */
2977 printk("\nXGIfb: I/O error!!!");
2978 return -EIO;
2981 switch (xgi_video_info.chip_id) {
2982 case PCI_DEVICE_ID_XG_20:
2983 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2984 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2985 if (CR48&GPIOG_READ)
2986 xgi_video_info.chip = XG21;
2987 else
2988 xgi_video_info.chip = XG20;
2989 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2990 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2991 break;
2992 case PCI_DEVICE_ID_XG_40:
2993 xgi_video_info.chip = XG40;
2994 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2995 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2996 break;
2997 case PCI_DEVICE_ID_XG_41:
2998 xgi_video_info.chip = XG41;
2999 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3000 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3001 break;
3002 case PCI_DEVICE_ID_XG_42:
3003 xgi_video_info.chip = XG42;
3004 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3005 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3006 break;
3007 case PCI_DEVICE_ID_XG_27:
3008 xgi_video_info.chip = XG27;
3009 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3010 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3011 break;
3012 default:
3013 return -ENODEV;
3016 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
3017 XGIhw_ext.jChipType = xgi_video_info.chip;
3019 switch (xgi_video_info.chip) {
3020 case XG40:
3021 case XG41:
3022 case XG42:
3023 case XG45:
3024 case XG20:
3025 case XG21:
3026 case XG27:
3027 XGIhw_ext.bIntegratedMMEnabled = 1;
3028 break;
3029 default:
3030 break;
3033 XGIhw_ext.pDevice = NULL;
3034 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
3035 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
3037 if (XGIhw_ext.pjVirtualRomBase)
3038 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
3039 else
3040 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3041 } else {
3042 XGIhw_ext.pjVirtualRomBase = NULL;
3043 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3045 XGIhw_ext.pjCustomizedROMImage = NULL;
3046 XGIhw_ext.bSkipDramSizing = 0;
3047 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3048 /* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
3049 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3051 XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
3052 if (XGIhw_ext.pSR == NULL) {
3053 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3054 return -ENODEV;
3056 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3058 XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
3059 if (XGIhw_ext.pCR == NULL) {
3060 vfree(XGIhw_ext.pSR);
3061 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3062 return -ENODEV;
3064 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3066 if (!XGIvga_enabled) {
3067 /* Mapping Max FB Size for 315 Init */
3068 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3069 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3070 #ifdef LINUXBIOS
3071 printk("XGIfb: XGIInit() ...");
3072 /* XGIInitNewt for LINUXBIOS only */
3073 if (XGIInitNew(&XGIhw_ext))
3074 printk("OK\n");
3075 else
3076 printk("Fail\n");
3077 #endif
3079 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3083 #ifdef LINUXBIOS
3084 else {
3085 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3086 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3088 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3090 /* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
3091 /* Set SR13 ,14 temporarily for UDtech */
3092 outXGIIDXREG(XGISR, 0x13, 0x45);
3093 outXGIIDXREG(XGISR, 0x14, 0x51);
3097 #endif
3098 if (XGIfb_get_dram_size()) {
3099 vfree(XGIhw_ext.pSR);
3100 vfree(XGIhw_ext.pCR);
3101 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3102 return -ENODEV;
3105 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3106 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3107 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3108 /* Enable 2D accelerator engine */
3109 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3112 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3114 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) {
3115 printk("unable request memory size %x", xgi_video_info.video_size);
3116 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3117 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3118 vfree(XGIhw_ext.pSR);
3119 vfree(XGIhw_ext.pCR);
3120 return -ENODEV;
3123 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO")) {
3124 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3125 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3126 vfree(XGIhw_ext.pSR);
3127 vfree(XGIhw_ext.pCR);
3128 return -ENODEV;
3131 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3132 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3133 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3135 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3136 xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
3138 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3139 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase, XGIfb_mmio_size / 1024);
3140 printk("XGIfb: XGIInitNew() ...");
3141 if (XGIInitNew(&XGIhw_ext))
3142 printk("OK\n");
3143 else
3144 printk("Fail\n");
3146 if (XGIfb_heap_init())
3147 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3149 xgi_video_info.mtrr = (unsigned int) 0;
3151 if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
3152 xgi_video_info.hasVB = HASVB_NONE;
3153 if ((xgi_video_info.chip == XG20) || (xgi_video_info.chip == XG27)) {
3154 xgi_video_info.hasVB = HASVB_NONE;
3155 } else if (xgi_video_info.chip == XG21) {
3156 inXGIIDXREG(XGICR, 0x38, CR38);
3157 if ((CR38&0xE0) == 0xC0) {
3158 xgi_video_info.disp_state = DISPTYPE_LCD;
3159 if (!XGIfb_GetXG21LVDSData()) {
3160 int m;
3161 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3162 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3163 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3164 XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
3168 } else if ((CR38&0xE0) == 0x60) {
3169 xgi_video_info.hasVB = HASVB_CHRONTEL;
3170 } else {
3171 xgi_video_info.hasVB = HASVB_NONE;
3173 } else {
3174 XGIfb_get_VB_type();
3177 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3179 XGIhw_ext.ulExternalChip = 0;
3181 switch (xgi_video_info.hasVB) {
3182 case HASVB_301:
3183 inXGIIDXREG(XGIPART4, 0x01, reg);
3184 if (reg >= 0xE0) {
3185 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3186 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3187 } else if (reg >= 0xD0) {
3188 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3189 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
3191 /* else if (reg >= 0xB0) {
3192 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3193 inXGIIDXREG(XGIPART4, 0x23, reg1);
3194 printk("XGIfb: XGI301B bridge detected\n");
3195 } */
3196 else {
3197 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3198 printk("XGIfb: XGI301 bridge detected\n");
3200 break;
3201 case HASVB_302:
3202 inXGIIDXREG(XGIPART4, 0x01, reg);
3203 if (reg >= 0xE0) {
3204 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3205 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3206 } else if (reg >= 0xD0) {
3207 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3208 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
3209 } else if (reg >= 0xB0) {
3210 inXGIIDXREG(XGIPART4, 0x23, reg1);
3212 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3214 } else {
3215 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3216 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3218 break;
3219 case HASVB_LVDS:
3220 XGIhw_ext.ulExternalChip = 0x1;
3221 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3222 break;
3223 case HASVB_TRUMPION:
3224 XGIhw_ext.ulExternalChip = 0x2;
3225 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3226 break;
3227 case HASVB_CHRONTEL:
3228 XGIhw_ext.ulExternalChip = 0x4;
3229 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3230 break;
3231 case HASVB_LVDS_CHRONTEL:
3232 XGIhw_ext.ulExternalChip = 0x5;
3233 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3234 break;
3235 default:
3236 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3237 break;
3240 if (xgi_video_info.hasVB != HASVB_NONE)
3241 XGIfb_detect_VB();
3243 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3244 if (XGIfb_crt1off)
3245 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3246 else
3247 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3248 } else {
3249 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3252 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3253 if (!enable_dstn) {
3254 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3255 reg &= 0x0f;
3256 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3258 } else {
3259 /* TW: FSTN/DSTN */
3260 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3264 XGIfb_detectedpdc = 0;
3266 XGIfb_detectedlcda = 0xff;
3267 #ifndef LINUXBIOS
3269 /* TW: Try to find about LCDA */
3271 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3272 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3273 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
3274 int tmp;
3275 inXGIIDXREG(XGICR, 0x34, tmp);
3276 if (tmp <= 0x13) {
3277 /* Currently on LCDA? (Some BIOSes leave CR38) */
3278 inXGIIDXREG(XGICR, 0x38, tmp);
3279 if ((tmp & 0x03) == 0x03) {
3280 /* XGI_Pr.XGI_UseLCDA = 1; */
3281 } else {
3282 /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
3283 inXGIIDXREG(XGICR, 0x35, tmp);
3284 if (tmp & 0x01) {
3285 /* XGI_Pr.XGI_UseLCDA = 1; */
3286 } else {
3287 inXGIIDXREG(XGICR, 0x30, tmp);
3288 if (tmp & 0x20) {
3289 inXGIIDXREG(XGIPART1, 0x13, tmp);
3290 if (tmp & 0x04) {
3291 /* XGI_Pr.XGI_UseLCDA = 1; */
3300 #endif
3302 if (xgifb_mode_idx >= 0)
3303 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3305 if (xgifb_mode_idx < 0) {
3306 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3307 case DISPTYPE_LCD:
3308 xgifb_mode_idx = DEFAULT_LCDMODE;
3309 if (xgi_video_info.chip == XG21)
3310 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3311 break;
3312 case DISPTYPE_TV:
3313 xgifb_mode_idx = DEFAULT_TVMODE;
3314 break;
3315 default:
3316 xgifb_mode_idx = DEFAULT_MODE;
3317 break;
3321 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3323 if (xgi_video_info.refresh_rate == 0)
3324 xgi_video_info.refresh_rate = 60; /* yilin set default refresh rate */
3325 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
3326 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3327 xgi_video_info.refresh_rate = 60;
3330 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3331 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3332 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3333 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3334 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3335 switch (xgi_video_info.video_bpp) {
3336 case 8:
3337 xgi_video_info.DstColor = 0x0000;
3338 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3339 xgi_video_info.video_cmap_len = 256;
3340 break;
3341 case 16:
3342 xgi_video_info.DstColor = 0x8000;
3343 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3344 xgi_video_info.video_cmap_len = 16;
3345 break;
3346 case 32:
3347 xgi_video_info.DstColor = 0xC000;
3348 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3349 xgi_video_info.video_cmap_len = 16;
3350 break;
3351 default:
3352 xgi_video_info.video_cmap_len = 16;
3353 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3354 break;
3357 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3358 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3359 xgi_video_info.refresh_rate);
3361 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3362 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3363 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3365 XGIfb_bpp_to_var(&default_var);
3367 default_var.pixclock = (u32) (1000000000 /
3368 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3369 XGIfb_mode_no, XGIfb_rate_idx));
3371 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3372 XGIfb_mode_no, XGIfb_rate_idx,
3373 &default_var.left_margin, &default_var.right_margin,
3374 &default_var.upper_margin, &default_var.lower_margin,
3375 &default_var.hsync_len, &default_var.vsync_len,
3376 &default_var.sync, &default_var.vmode)) {
3378 if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3379 default_var.yres <<= 1;
3380 default_var.yres_virtual <<= 1;
3381 } else if ((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3382 default_var.pixclock >>= 1;
3383 default_var.yres >>= 1;
3384 default_var.yres_virtual >>= 1;
3389 xgi_video_info.accel = 0;
3390 if (XGIfb_accel) {
3391 xgi_video_info.accel = -1;
3392 default_var.accel_flags |= FB_ACCELF_TEXT;
3393 XGIfb_initaccel();
3396 fb_info->flags = FBINFO_FLAG_DEFAULT;
3397 fb_info->var = default_var;
3398 fb_info->fix = XGIfb_fix;
3399 fb_info->par = &xgi_video_info;
3400 fb_info->screen_base = xgi_video_info.video_vbase;
3401 fb_info->fbops = &XGIfb_ops;
3402 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3403 fb_info->pseudo_palette = pseudo_palette;
3405 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3407 #ifdef CONFIG_MTRR
3408 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3409 (unsigned int) xgi_video_info.video_size,
3410 MTRR_TYPE_WRCOMB, 1);
3411 if (xgi_video_info.mtrr)
3412 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3413 #endif
3415 if (register_framebuffer(fb_info) < 0)
3416 return -EINVAL;
3418 XGIfb_registered = 1;
3420 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3421 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3425 dumpVGAReg();
3427 return 0;
3430 /*****************************************************/
3431 /* PCI DEVICE HANDLING */
3432 /*****************************************************/
3434 static void __devexit xgifb_remove(struct pci_dev *pdev)
3436 /* Unregister the framebuffer */
3437 /* if (xgi_video_info.registered) { */
3438 unregister_framebuffer(fb_info);
3439 framebuffer_release(fb_info);
3440 /* } */
3442 pci_set_drvdata(pdev, NULL);
3446 static struct pci_driver xgifb_driver = {
3447 .name = "xgifb",
3448 .id_table = xgifb_pci_table,
3449 .probe = xgifb_probe,
3450 .remove = __devexit_p(xgifb_remove)
3453 XGIINITSTATIC int __init xgifb_init(void)
3455 char *option = NULL;
3457 if (fb_get_options("xgifb", &option))
3458 return -ENODEV;
3459 XGIfb_setup(option);
3461 return pci_register_driver(&xgifb_driver);
3464 #ifndef MODULE
3465 module_init(xgifb_init);
3466 #endif
3468 /*****************************************************/
3469 /* MODULE */
3470 /*****************************************************/
3472 #ifdef MODULE
3474 static char *mode = NULL;
3475 static int vesa = 0;
3476 static unsigned int rate = 0;
3477 static unsigned int mem = 0;
3478 static char *forcecrt2type = NULL;
3479 static int forcecrt1 = -1;
3480 static int pdc = -1;
3481 static int pdc1 = -1;
3482 static int noaccel = -1;
3483 static int noypan = -1;
3484 static int nomax = -1;
3485 static int userom = -1;
3486 static int useoem = -1;
3487 static char *tvstandard = NULL;
3488 static int nocrt2rate = 0;
3489 static int scalelcd = -1;
3490 static char *specialtiming = NULL;
3491 static int lvdshl = -1;
3492 static int tvxposoffset = 0, tvyposoffset = 0;
3493 #if !defined(__i386__) && !defined(__x86_64__)
3494 static int resetcard = 0;
3495 static int videoram = 0;
3496 #endif
3498 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3499 MODULE_LICENSE("GPL");
3500 MODULE_AUTHOR("XGITECH , Others");
3502 module_param(mem, int, 0);
3503 module_param(noaccel, int, 0);
3504 module_param(noypan, int, 0);
3505 module_param(nomax, int, 0);
3506 module_param(userom, int, 0);
3507 module_param(useoem, int, 0);
3508 module_param(mode, charp, 0);
3509 module_param(vesa, int, 0);
3510 module_param(rate, int, 0);
3511 module_param(forcecrt1, int, 0);
3512 module_param(forcecrt2type, charp, 0);
3513 module_param(scalelcd, int, 0);
3514 module_param(pdc, int, 0);
3515 module_param(pdc1, int, 0);
3516 module_param(specialtiming, charp, 0);
3517 module_param(lvdshl, int, 0);
3518 module_param(tvstandard, charp, 0);
3519 module_param(tvxposoffset, int, 0);
3520 module_param(tvyposoffset, int, 0);
3521 module_param(filter, int, 0);
3522 module_param(nocrt2rate, int, 0);
3523 #if !defined(__i386__) && !defined(__x86_64__)
3524 module_param(resetcard, int, 0);
3525 module_param(videoram, int, 0);
3526 #endif
3528 MODULE_PARM_DESC(mem,
3529 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3530 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3531 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3532 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3533 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3534 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3535 "for XFree86 4.x/X.org 6.7 and later.\n");
3537 MODULE_PARM_DESC(noaccel,
3538 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3539 "(default: 0)\n");
3541 MODULE_PARM_DESC(noypan,
3542 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3543 "will be performed by redrawing the screen. (default: 0)\n");
3545 MODULE_PARM_DESC(nomax,
3546 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3547 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3548 "this is set to anything other than 0, xgifb will not do this and thereby\n"
3549 "enable the user to positively specify a virtual Y size of the screen using\n"
3550 "fbset. (default: 0)\n");
3552 MODULE_PARM_DESC(mode,
3553 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3554 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3555 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3556 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3558 MODULE_PARM_DESC(vesa,
3559 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3560 "0x117 (default: 0x0103)\n");
3562 MODULE_PARM_DESC(rate,
3563 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3564 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3565 "will be ignored (default: 60)\n");
3567 MODULE_PARM_DESC(forcecrt1,
3568 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
3569 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3570 "0=CRT1 OFF) (default: [autodetected])\n");
3572 MODULE_PARM_DESC(forcecrt2type,
3573 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3574 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3575 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3576 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3577 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3578 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3579 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3580 "depends on the very hardware in use. (default: [autodetected])\n");
3582 MODULE_PARM_DESC(scalelcd,
3583 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3584 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3585 "show black bars around the image, TMDS panels will probably do the scaling\n"
3586 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3588 MODULE_PARM_DESC(pdc,
3589 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3590 "should detect this correctly in most cases; however, sometimes this is not\n"
3591 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3592 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3593 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3594 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3596 MODULE_PARM_DESC(pdc1,
3597 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3598 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3599 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3600 "implemented yet.\n");
3602 MODULE_PARM_DESC(specialtiming,
3603 "\nPlease refer to documentation for more information on this option.\n");
3605 MODULE_PARM_DESC(lvdshl,
3606 "\nPlease refer to documentation for more information on this option.\n");
3608 MODULE_PARM_DESC(tvstandard,
3609 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3610 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3612 MODULE_PARM_DESC(tvxposoffset,
3613 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3614 "Default: 0\n");
3616 MODULE_PARM_DESC(tvyposoffset,
3617 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3618 "Default: 0\n");
3620 MODULE_PARM_DESC(filter,
3621 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3622 "(Possible values 0-7, default: [no filter])\n");
3624 MODULE_PARM_DESC(nocrt2rate,
3625 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3626 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3628 static int __init xgifb_init_module(void)
3630 printk("\nXGIfb_init_module");
3631 if (mode)
3632 XGIfb_search_mode(mode);
3633 else if (vesa != -1)
3634 XGIfb_search_vesamode(vesa);
3636 return xgifb_init();
3639 static void __exit xgifb_remove_module(void)
3641 pci_unregister_driver(&xgifb_driver);
3642 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3645 module_init(xgifb_init_module);
3646 module_exit(xgifb_remove_module);
3648 #endif /* /MODULE */
3650 EXPORT_SYMBOL(XGI_malloc);
3651 EXPORT_SYMBOL(XGI_free);