staging: xgifb: delete redundant casts from mtrr_add() call
[pandora-kernel.git] / drivers / staging / xgifb / XGI_main_26.c
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  */
6
7 /* #include <linux/config.h> */
8 #include <linux/module.h>
9 #include <linux/moduleparam.h>
10 #include <linux/kernel.h>
11 #include <linux/spinlock.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/mm.h>
15 #include <linux/tty.h>
16 #include <linux/slab.h>
17 #include <linux/delay.h>
18 #include <linux/fb.h>
19 #include <linux/console.h>
20 #include <linux/selection.h>
21 #include <linux/ioport.h>
22 #include <linux/init.h>
23 #include <linux/pci.h>
24 #include <linux/vmalloc.h>
25 #include <linux/vt_kern.h>
26 #include <linux/capability.h>
27 #include <linux/fs.h>
28 #include <linux/types.h>
29 #include <linux/proc_fs.h>
30
31 #include <linux/io.h>
32 #ifdef CONFIG_MTRR
33 #include <asm/mtrr.h>
34 #endif
35
36 #include "XGIfb.h"
37 #include "vgatypes.h"
38 #include "XGI_main.h"
39 #include "vb_init.h"
40 #include "vb_util.h"
41 #include "vb_setmode.h"
42
43 #define Index_CR_GPIO_Reg1 0x48
44 #define Index_CR_GPIO_Reg3 0x4a
45
46 #define GPIOG_EN    (1<<6)
47 #define GPIOG_READ  (1<<1)
48
49 #define XGIFB_ROM_SIZE  65536
50
51 static char *mode;
52 static int vesa = -1;
53
54 /* -------------------- Macro definitions ---------------------------- */
55
56 #undef XGIFBDEBUG
57
58 #ifdef XGIFBDEBUG
59 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
60 #else
61 #define DPRINTK(fmt, args...)
62 #endif
63
64 #ifdef XGIFBDEBUG
65 static void dumpVGAReg(void)
66 {
67         u8 i, reg;
68
69         xgifb_reg_set(XGISR, 0x05, 0x86);
70         /*
71         xgifb_reg_set(XGISR, 0x08, 0x4f);
72         xgifb_reg_set(XGISR, 0x0f, 0x20);
73         xgifb_reg_set(XGISR, 0x11, 0x4f);
74         xgifb_reg_set(XGISR, 0x13, 0x45);
75         xgifb_reg_set(XGISR, 0x14, 0x51);
76         xgifb_reg_set(XGISR, 0x1e, 0x41);
77         xgifb_reg_set(XGISR, 0x1f, 0x0);
78         xgifb_reg_set(XGISR, 0x20, 0xa1);
79         xgifb_reg_set(XGISR, 0x22, 0xfb);
80         xgifb_reg_set(XGISR, 0x26, 0x22);
81         xgifb_reg_set(XGISR, 0x3e, 0x07);
82         */
83
84         /* xgifb_reg_set(XGICR, 0x19, 0x00); */
85         /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
86         /* xgifb_reg_set(XGICR, 0x22, 0xff); */
87         /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
88
89         /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
90
91         /* xgifb_reg_set(XGICR, 0x57, 0x0); */
92         /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
93
94         /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
95         /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
96         /*
97         xgifb_reg_set(XGICR, 0x99, 0x1);
98         xgifb_reg_set(XGICR, 0x41, 0x40);
99         */
100
101         for (i = 0; i < 0x4f; i++) {
102                 reg = xgifb_reg_get(XGISR, i);
103                 printk("\no 3c4 %x", i);
104                 printk("\ni 3c5 => %x", reg);
105         }
106
107         for (i = 0; i < 0xF0; i++) {
108                 reg = xgifb_reg_get(XGICR, i);
109                 printk("\no 3d4 %x", i);
110                 printk("\ni 3d5 => %x", reg);
111         }
112         /*
113         xgifb_reg_set(XGIPART1,0x2F,1);
114         for (i=1; i < 0x50; i++) {
115                 reg = xgifb_reg_get(XGIPART1, i);
116                 printk("\no d004 %x", i);
117                 printk("\ni d005 => %x", reg);
118         }
119
120         for (i=0; i < 0x50; i++) {
121                  reg = xgifb_reg_get(XGIPART2, i);
122                  printk("\no d010 %x", i);
123                  printk("\ni d011 => %x", reg);
124         }
125         for (i=0; i < 0x50; i++) {
126                 reg = xgifb_reg_get(XGIPART3, i);
127                 printk("\no d012 %x",i);
128                 printk("\ni d013 => %x",reg);
129         }
130         for (i=0; i < 0x50; i++) {
131                 reg = xgifb_reg_get(XGIPART4, i);
132                 printk("\no d014 %x",i);
133                 printk("\ni d015 => %x",reg);
134         }
135         */
136 }
137 #else
138 static inline void dumpVGAReg(void)
139 {
140 }
141 #endif
142
143 /* data for XGI components */
144 struct video_info xgi_video_info;
145
146 #if 1
147 #define DEBUGPRN(x)
148 #else
149 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
150 #endif
151
152 /* --------------- Hardware Access Routines -------------------------- */
153
154 static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
155                 struct xgi_hw_device_info *HwDeviceExtension,
156                 unsigned char modeno, unsigned char rateindex)
157 {
158         unsigned short ModeNo = modeno;
159         unsigned short ModeIdIndex = 0, ClockIndex = 0;
160         unsigned short RefreshRateTableIndex = 0;
161
162         /* unsigned long  temp = 0; */
163         int Clock;
164         XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
165         InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
166
167         RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
168                         ModeIdIndex, XGI_Pr);
169
170         /*
171         temp = XGI_SearchModeID(ModeNo , &ModeIdIndex,  XGI_Pr) ;
172         if (!temp) {
173                 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
174                 return 65000;
175         }
176
177         RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
178         RefreshRateTableIndex += (rateindex - 1);
179
180         */
181         ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
182
183         Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
184
185         return Clock;
186 }
187
188 static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
189                 struct xgi_hw_device_info *HwDeviceExtension,
190                 unsigned char modeno, unsigned char rateindex,
191                 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
192                 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
193                 u32 *vmode)
194 {
195         unsigned short ModeNo = modeno;
196         unsigned short ModeIdIndex = 0, index = 0;
197         unsigned short RefreshRateTableIndex = 0;
198
199         unsigned short VRE, VBE, VRS, VBS, VDE, VT;
200         unsigned short HRE, HBE, HRS, HBS, HDE, HT;
201         unsigned char sr_data, cr_data, cr_data2;
202         unsigned long cr_data3;
203         int A, B, C, D, E, F, temp, j;
204         XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
205         InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
206         RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
207                         ModeIdIndex, XGI_Pr);
208         /*
209         temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
210         if (!temp)
211                 return 0;
212
213         RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
214         RefreshRateTableIndex += (rateindex - 1);
215         */
216         index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
217
218         sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
219
220         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
221
222         /* Horizontal total */
223         HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
224         A = HT + 5;
225
226         /*
227         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
228
229         Horizontal display enable end
230         HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
231         */
232         HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
233         E = HDE + 1;
234
235         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
236
237         /* Horizontal retrace (=sync) start */
238         HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
239         F = HRS - E - 3;
240
241         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
242
243         /* Horizontal blank start */
244         HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
245
246         sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
247
248         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
249
250         cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
251
252         /* Horizontal blank end */
253         HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
254                         | ((unsigned short) (sr_data & 0x03) << 6);
255
256         /* Horizontal retrace (=sync) end */
257         HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
258
259         temp = HBE - ((E - 1) & 255);
260         B = (temp > 0) ? temp : (temp + 256);
261
262         temp = HRE - ((E + F + 3) & 63);
263         C = (temp > 0) ? temp : (temp + 64);
264
265         D = B - F - C;
266
267         *left_margin = D * 8;
268         *right_margin = F * 8;
269         *hsync_len = C * 8;
270
271         sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
272
273         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
274
275         cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
276
277         /* Vertical total */
278         VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
279                         | ((unsigned short) (cr_data2 & 0x20) << 4)
280                         | ((unsigned short) (sr_data & 0x01) << 10);
281         A = VT + 2;
282
283         /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
284
285         /* Vertical display enable end */
286         /*
287         VDE = (cr_data & 0xff) |
288                 ((unsigned short) (cr_data2 & 0x02) << 7) |
289                 ((unsigned short) (cr_data2 & 0x40) << 3) |
290                 ((unsigned short) (sr_data & 0x02) << 9);
291         */
292         VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
293         E = VDE + 1;
294
295         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
296
297         /* Vertical retrace (=sync) start */
298         VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
299                         | ((unsigned short) (cr_data2 & 0x80) << 2)
300                         | ((unsigned short) (sr_data & 0x08) << 7);
301         F = VRS + 1 - E;
302
303         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
304
305         cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
306
307         /* Vertical blank start */
308         VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
309                         | ((unsigned short) (cr_data3 & 0x20) << 4)
310                         | ((unsigned short) (sr_data & 0x04) << 8);
311
312         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
313
314         /* Vertical blank end */
315         VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
316         temp = VBE - ((E - 1) & 511);
317         B = (temp > 0) ? temp : (temp + 512);
318
319         cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
320
321         /* Vertical retrace (=sync) end */
322         VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
323         temp = VRE - ((E + F - 1) & 31);
324         C = (temp > 0) ? temp : (temp + 32);
325
326         D = B - F - C;
327
328         *upper_margin = D;
329         *lower_margin = F;
330         *vsync_len = C;
331
332         if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
333                 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
334         else
335                 *sync |= FB_SYNC_VERT_HIGH_ACT;
336
337         if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
338                 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
339         else
340                 *sync |= FB_SYNC_HOR_HIGH_ACT;
341
342         *vmode = FB_VMODE_NONINTERLACED;
343         if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
344                 *vmode = FB_VMODE_INTERLACED;
345         else {
346                 j = 0;
347                 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
348                         if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
349                             XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
350                                 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
351                                     DoubleScanMode) {
352                                         *vmode = FB_VMODE_DOUBLE;
353                                 }
354                                 break;
355                         }
356                         j++;
357                 }
358         }
359
360         return 1;
361 }
362
363 static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
364 {
365         XGI_Pr->RelIO = BaseAddr;
366         XGI_Pr->P3c4 = BaseAddr + 0x14;
367         XGI_Pr->P3d4 = BaseAddr + 0x24;
368         XGI_Pr->P3c0 = BaseAddr + 0x10;
369         XGI_Pr->P3ce = BaseAddr + 0x1e;
370         XGI_Pr->P3c2 = BaseAddr + 0x12;
371         XGI_Pr->P3ca = BaseAddr + 0x1a;
372         XGI_Pr->P3c6 = BaseAddr + 0x16;
373         XGI_Pr->P3c7 = BaseAddr + 0x17;
374         XGI_Pr->P3c8 = BaseAddr + 0x18;
375         XGI_Pr->P3c9 = BaseAddr + 0x19;
376         XGI_Pr->P3da = BaseAddr + 0x2A;
377         /* Digital video interface registers (LCD) */
378         XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04;
379         /* 301 TV Encoder registers */
380         XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10;
381         /* 301 Macrovision registers */
382         XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12;
383         /* 301 VGA2 (and LCD) registers */
384         XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14;
385         /* 301 palette address port registers */
386         XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2;
387
388 }
389
390 /* ------------ Interface for init & mode switching code ------------- */
391
392 static unsigned char XGIfb_query_VGA_config_space(
393                 struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
394                 unsigned long set, unsigned long *value)
395 {
396         static struct pci_dev *pdev;
397         static unsigned char init, valid_pdev;
398
399         if (!set)
400                 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
401         else
402                 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
403
404         if (!init) {
405                 init = 1;
406                 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
407                                 pdev);
408                 if (pdev) {
409                         valid_pdev = 1;
410                         pci_dev_put(pdev);
411                 }
412         }
413
414         if (!valid_pdev) {
415                 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
416                                 xgi_video_info.chip_id);
417                 return 0;
418         }
419
420         if (set == 0)
421                 pci_read_config_dword(pdev, offset, (u32 *) value);
422         else
423                 pci_write_config_dword(pdev, offset, (u32)(*value));
424
425         return 1;
426 }
427
428 /* ------------------ Internal helper routines ----------------- */
429
430 static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
431 {
432
433         int found_mode = 0;
434         int XGIfb_mode_idx = 0;
435
436         found_mode = 0;
437         while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
438                         && (XGIbios_mode[XGIfb_mode_idx].xres
439                                         <= XGI21_LCDCapList[0].LVDSHDE)) {
440                 if ((XGIbios_mode[XGIfb_mode_idx].xres
441                                 == XGI21_LCDCapList[0].LVDSHDE)
442                                 && (XGIbios_mode[XGIfb_mode_idx].yres
443                                                 == XGI21_LCDCapList[0].LVDSVDE)
444                                 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
445                         XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
446                         found_mode = 1;
447                         break;
448                 }
449                 XGIfb_mode_idx++;
450         }
451         if (!found_mode)
452                 XGIfb_mode_idx = -1;
453
454         return XGIfb_mode_idx;
455 }
456
457 static void XGIfb_search_mode(const char *name)
458 {
459         int i = 0, j = 0, l;
460
461         while (XGIbios_mode[i].mode_no != 0) {
462                 l = min(strlen(name), strlen(XGIbios_mode[i].name));
463                 if (!strncmp(name, XGIbios_mode[i].name, l)) {
464                         xgifb_mode_idx = i;
465                         j = 1;
466                         break;
467                 }
468                 i++;
469         }
470         if (!j)
471                 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
472 }
473
474 static void XGIfb_search_vesamode(unsigned int vesamode)
475 {
476         int i = 0, j = 0;
477
478         if (vesamode == 0)
479                 goto invalid;
480
481         vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
482
483         while (XGIbios_mode[i].mode_no != 0) {
484                 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
485                     (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
486                         xgifb_mode_idx = i;
487                         j = 1;
488                         break;
489                 }
490                 i++;
491         }
492
493 invalid:
494         if (!j)
495                 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
496 }
497
498 static int XGIfb_GetXG21LVDSData(void)
499 {
500         u8 tmp;
501         unsigned char *pData;
502         int i, j, k;
503
504         tmp = xgifb_reg_get(XGISR, 0x1e);
505         xgifb_reg_set(XGISR, 0x1e, tmp | 4);
506
507         pData = xgi_video_info.mmio_vbase + 0x20000;
508         if ((pData[0x0] == 0x55) &&
509             (pData[0x1] == 0xAA) &&
510             (pData[0x65] & 0x1)) {
511                 i = pData[0x316] | (pData[0x317] << 8);
512                 j = pData[i - 1];
513                 if (j == 0xff)
514                         j = 1;
515
516                 k = 0;
517                 do {
518                         XGI21_LCDCapList[k].LVDS_Capability = pData[i]
519                                         | (pData[i + 1] << 8);
520                         XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
521                                         + 3] << 8);
522                         XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
523                                         + 5] << 8);
524                         XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
525                                         + 7] << 8);
526                         XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
527                                         + 9] << 8);
528                         XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
529                                         + 11] << 8);
530                         XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
531                                         + 13] << 8);
532                         XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
533                                         | (pData[i + 15] << 8);
534                         XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
535                                         | (pData[i + 17] << 8);
536                         XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
537                         XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
538                         XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
539                         XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
540                         XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
541                         XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
542                         XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
543                         i += 25;
544                         j--;
545                         k++;
546                 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
547                                 / sizeof(struct XGI21_LVDSCapStruct))));
548                 return 1;
549         }
550         return 0;
551 }
552
553 static int XGIfb_validate_mode(int myindex)
554 {
555         u16 xres, yres;
556
557         if (xgi_video_info.chip == XG21) {
558                 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
559                                 == DISPTYPE_LCD) {
560                         xres = XGI21_LCDCapList[0].LVDSHDE;
561                         yres = XGI21_LCDCapList[0].LVDSVDE;
562                         if (XGIbios_mode[myindex].xres > xres)
563                                 return -1;
564                         if (XGIbios_mode[myindex].yres > yres)
565                                 return -1;
566                         if ((XGIbios_mode[myindex].xres < xres) &&
567                             (XGIbios_mode[myindex].yres < yres)) {
568                                 if (XGIbios_mode[myindex].bpp > 8)
569                                         return -1;
570                         }
571
572                 }
573                 return myindex;
574
575         }
576
577         /* FIXME: for now, all is valid on XG27 */
578         if (xgi_video_info.chip == XG27)
579                 return myindex;
580
581         if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
582                 return -1;
583
584         switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
585         case DISPTYPE_LCD:
586                 switch (XGIhw_ext.ulCRT2LCDType) {
587                 case LCD_640x480:
588                         xres = 640;
589                         yres = 480;
590                         break;
591                 case LCD_800x600:
592                         xres = 800;
593                         yres = 600;
594                         break;
595                 case LCD_1024x600:
596                         xres = 1024;
597                         yres = 600;
598                         break;
599                 case LCD_1024x768:
600                         xres = 1024;
601                         yres = 768;
602                         break;
603                 case LCD_1152x768:
604                         xres = 1152;
605                         yres = 768;
606                         break;
607                 case LCD_1280x960:
608                         xres = 1280;
609                         yres = 960;
610                         break;
611                 case LCD_1280x768:
612                         xres = 1280;
613                         yres = 768;
614                         break;
615                 case LCD_1280x1024:
616                         xres = 1280;
617                         yres = 1024;
618                         break;
619                 case LCD_1400x1050:
620                         xres = 1400;
621                         yres = 1050;
622                         break;
623                 case LCD_1600x1200:
624                         xres = 1600;
625                         yres = 1200;
626                         break;
627                 /* case LCD_320x480: */ /* TW: FSTN */
628                         /*
629                         xres =  320;
630                         yres =  480;
631                         break;
632                         */
633                 default:
634                         xres = 0;
635                         yres = 0;
636                         break;
637                 }
638                 if (XGIbios_mode[myindex].xres > xres)
639                         return -1;
640                 if (XGIbios_mode[myindex].yres > yres)
641                         return -1;
642                 if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
643                     (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
644                         switch (XGIbios_mode[myindex].xres) {
645                         case 512:
646                                 if (XGIbios_mode[myindex].yres != 512)
647                                         return -1;
648                                 if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
649                                         return -1;
650                                 break;
651                         case 640:
652                                 if ((XGIbios_mode[myindex].yres != 400)
653                                                 && (XGIbios_mode[myindex].yres
654                                                                 != 480))
655                                         return -1;
656                                 break;
657                         case 800:
658                                 if (XGIbios_mode[myindex].yres != 600)
659                                         return -1;
660                                 break;
661                         case 1024:
662                                 if ((XGIbios_mode[myindex].yres != 600) &&
663                                     (XGIbios_mode[myindex].yres != 768))
664                                         return -1;
665                                 if ((XGIbios_mode[myindex].yres == 600) &&
666                                     (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
667                                         return -1;
668                                 break;
669                         case 1152:
670                                 if ((XGIbios_mode[myindex].yres) != 768)
671                                         return -1;
672                                 if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
673                                         return -1;
674                                 break;
675                         case 1280:
676                                 if ((XGIbios_mode[myindex].yres != 768) &&
677                                     (XGIbios_mode[myindex].yres != 1024))
678                                         return -1;
679                                 if ((XGIbios_mode[myindex].yres == 768) &&
680                                     (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
681                                         return -1;
682                                 break;
683                         case 1400:
684                                 if (XGIbios_mode[myindex].yres != 1050)
685                                         return -1;
686                                 break;
687                         case 1600:
688                                 if (XGIbios_mode[myindex].yres != 1200)
689                                         return -1;
690                                 break;
691                         default:
692                                 return -1;
693                         }
694                 } else {
695                         switch (XGIbios_mode[myindex].xres) {
696                         case 512:
697                                 if (XGIbios_mode[myindex].yres != 512)
698                                         return -1;
699                                 break;
700                         case 640:
701                                 if ((XGIbios_mode[myindex].yres != 400) &&
702                                     (XGIbios_mode[myindex].yres != 480))
703                                         return -1;
704                                 break;
705                         case 800:
706                                 if (XGIbios_mode[myindex].yres != 600)
707                                         return -1;
708                                 break;
709                         case 1024:
710                                 if (XGIbios_mode[myindex].yres != 768)
711                                         return -1;
712                                 break;
713                         case 1280:
714                                 if ((XGIbios_mode[myindex].yres != 960) &&
715                                     (XGIbios_mode[myindex].yres != 1024))
716                                         return -1;
717                                 if (XGIbios_mode[myindex].yres == 960) {
718                                         if (XGIhw_ext.ulCRT2LCDType ==
719                                             LCD_1400x1050)
720                                                 return -1;
721                                 }
722                                 break;
723                         case 1400:
724                                 if (XGIbios_mode[myindex].yres != 1050)
725                                         return -1;
726                                 break;
727                         case 1600:
728                                 if (XGIbios_mode[myindex].yres != 1200)
729                                         return -1;
730                                 break;
731                         default:
732                                 return -1;
733                         }
734                 }
735                 break;
736         case DISPTYPE_TV:
737                 switch (XGIbios_mode[myindex].xres) {
738                 case 512:
739                 case 640:
740                 case 800:
741                         break;
742                 case 720:
743                         if (xgi_video_info.TV_type == TVMODE_NTSC) {
744                                 if (XGIbios_mode[myindex].yres != 480)
745                                         return -1;
746                         } else if (xgi_video_info.TV_type == TVMODE_PAL) {
747                                 if (XGIbios_mode[myindex].yres != 576)
748                                         return -1;
749                         }
750                         /*  TW: LVDS/CHRONTEL does not support 720 */
751                         if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
752                             xgi_video_info.hasVB == HASVB_CHRONTEL) {
753                                 return -1;
754                         }
755                         break;
756                 case 1024:
757                         if (xgi_video_info.TV_type == TVMODE_NTSC) {
758                                 if (XGIbios_mode[myindex].bpp == 32)
759                                         return -1;
760                         }
761                         break;
762                 default:
763                         return -1;
764                 }
765                 break;
766         case DISPTYPE_CRT2:
767                 if (XGIbios_mode[myindex].xres > 1280)
768                         return -1;
769                 break;
770         }
771         return myindex;
772
773 }
774
775 static void XGIfb_search_crt2type(const char *name)
776 {
777         int i = 0;
778
779         if (name == NULL)
780                 return;
781
782         while (XGI_crt2type[i].type_no != -1) {
783                 if (!strcmp(name, XGI_crt2type[i].name)) {
784                         XGIfb_crt2type = XGI_crt2type[i].type_no;
785                         XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
786                         break;
787                 }
788                 i++;
789         }
790         if (XGIfb_crt2type < 0)
791                 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
792 }
793
794 static u8 XGIfb_search_refresh_rate(unsigned int rate)
795 {
796         u16 xres, yres;
797         int i = 0;
798
799         xres = XGIbios_mode[xgifb_mode_idx].xres;
800         yres = XGIbios_mode[xgifb_mode_idx].yres;
801
802         XGIfb_rate_idx = 0;
803         while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
804                 if ((XGIfb_vrate[i].xres == xres) &&
805                     (XGIfb_vrate[i].yres == yres)) {
806                         if (XGIfb_vrate[i].refresh == rate) {
807                                 XGIfb_rate_idx = XGIfb_vrate[i].idx;
808                                 break;
809                         } else if (XGIfb_vrate[i].refresh > rate) {
810                                 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
811                                         DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
812                                                 rate, XGIfb_vrate[i].refresh);
813                                         XGIfb_rate_idx = XGIfb_vrate[i].idx;
814                                         xgi_video_info.refresh_rate =
815                                                 XGIfb_vrate[i].refresh;
816                                 } else if (((rate - XGIfb_vrate[i - 1].refresh)
817                                                 <= 2) && (XGIfb_vrate[i].idx
818                                                 != 1)) {
819                                         DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
820                                                 rate, XGIfb_vrate[i-1].refresh);
821                                         XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
822                                         xgi_video_info.refresh_rate =
823                                                 XGIfb_vrate[i - 1].refresh;
824                                 }
825                                 break;
826                         } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
827                                 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
828                                         rate, XGIfb_vrate[i].refresh);
829                                 XGIfb_rate_idx = XGIfb_vrate[i].idx;
830                                 break;
831                         }
832                 }
833                 i++;
834         }
835         if (XGIfb_rate_idx > 0) {
836                 return XGIfb_rate_idx;
837         } else {
838                 printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n",
839                        rate, xres, yres);
840                 return 0;
841         }
842 }
843
844 static void XGIfb_search_tvstd(const char *name)
845 {
846         int i = 0;
847
848         if (name == NULL)
849                 return;
850
851         while (XGI_tvtype[i].type_no != -1) {
852                 if (!strcmp(name, XGI_tvtype[i].name)) {
853                         XGIfb_tvmode = XGI_tvtype[i].type_no;
854                         break;
855                 }
856                 i++;
857         }
858 }
859
860 /* ----------- FBDev related routines for all series ----------- */
861
862 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
863 {
864         switch (var->bits_per_pixel) {
865         case 8:
866                 var->red.offset = var->green.offset = var->blue.offset = 0;
867                 var->red.length = var->green.length = var->blue.length = 6;
868                 xgi_video_info.video_cmap_len = 256;
869                 break;
870         case 16:
871                 var->red.offset = 11;
872                 var->red.length = 5;
873                 var->green.offset = 5;
874                 var->green.length = 6;
875                 var->blue.offset = 0;
876                 var->blue.length = 5;
877                 var->transp.offset = 0;
878                 var->transp.length = 0;
879                 xgi_video_info.video_cmap_len = 16;
880                 break;
881         case 32:
882                 var->red.offset = 16;
883                 var->red.length = 8;
884                 var->green.offset = 8;
885                 var->green.length = 8;
886                 var->blue.offset = 0;
887                 var->blue.length = 8;
888                 var->transp.offset = 24;
889                 var->transp.length = 8;
890                 xgi_video_info.video_cmap_len = 16;
891                 break;
892         }
893 }
894
895 /* --------------------- SetMode routines ------------------------- */
896
897 static void XGIfb_pre_setmode(void)
898 {
899         u8 cr30 = 0, cr31 = 0;
900
901         cr31 = xgifb_reg_get(XGICR, 0x31);
902         cr31 &= ~0x60;
903
904         switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
905         case DISPTYPE_CRT2:
906                 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
907                 cr31 |= XGI_DRIVER_MODE;
908                 break;
909         case DISPTYPE_LCD:
910                 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
911                 cr31 |= XGI_DRIVER_MODE;
912                 break;
913         case DISPTYPE_TV:
914                 if (xgi_video_info.TV_type == TVMODE_HIVISION)
915                         cr30 = (XGI_VB_OUTPUT_HIVISION
916                                         | XGI_SIMULTANEOUS_VIEW_ENABLE);
917                 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
918                         cr30 = (XGI_VB_OUTPUT_SVIDEO
919                                         | XGI_SIMULTANEOUS_VIEW_ENABLE);
920                 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
921                         cr30 = (XGI_VB_OUTPUT_COMPOSITE
922                                         | XGI_SIMULTANEOUS_VIEW_ENABLE);
923                 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
924                         cr30 = (XGI_VB_OUTPUT_SCART
925                                         | XGI_SIMULTANEOUS_VIEW_ENABLE);
926                 cr31 |= XGI_DRIVER_MODE;
927
928                 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
929                         cr31 |= 0x01;
930                 else
931                         cr31 &= ~0x01;
932                 break;
933         default: /* disable CRT2 */
934                 cr30 = 0x00;
935                 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
936         }
937
938         xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
939         xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
940         xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
941 }
942
943 static void XGIfb_post_setmode(void)
944 {
945         u8 reg;
946         unsigned char doit = 1;
947         /*
948         xgifb_reg_set(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
949         xgifb_reg_set(XGICR, 0x13, 0x00);
950         xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
951         *test*
952         */
953         if (xgi_video_info.video_bpp == 8) {
954                 /* TW: We can't switch off CRT1 on LVDS/Chrontel
955                  * in 8bpp Modes */
956                 if ((xgi_video_info.hasVB == HASVB_LVDS) ||
957                     (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
958                         doit = 0;
959                 }
960                 /* TW: We can't switch off CRT1 on 301B-DH
961                  * in 8bpp Modes if using LCD */
962                 if (xgi_video_info.disp_state & DISPTYPE_LCD)
963                         doit = 0;
964         }
965
966         /* TW: We can't switch off CRT1 if bridge is in slave mode */
967         if (xgi_video_info.hasVB != HASVB_NONE) {
968                 reg = xgifb_reg_get(XGIPART1, 0x00);
969
970                 if ((reg & 0x50) == 0x10)
971                         doit = 0;
972
973         } else {
974                 XGIfb_crt1off = 0;
975         }
976
977         reg = xgifb_reg_get(XGICR, 0x17);
978         if ((XGIfb_crt1off) && (doit))
979                 reg &= ~0x80;
980         else
981                 reg |= 0x80;
982         xgifb_reg_set(XGICR, 0x17, reg);
983
984         xgifb_reg_and(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
985
986         if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
987                         == HASVB_301)) {
988
989                 reg = xgifb_reg_get(XGIPART4, 0x01);
990
991                 if (reg < 0xB0) { /* Set filter for XGI301 */
992                         switch (xgi_video_info.video_width) {
993                         case 320:
994                                 filter_tb = (xgi_video_info.TV_type ==
995                                              TVMODE_NTSC) ? 4 : 12;
996                                 break;
997                         case 640:
998                                 filter_tb = (xgi_video_info.TV_type ==
999                                              TVMODE_NTSC) ? 5 : 13;
1000                                 break;
1001                         case 720:
1002                                 filter_tb = (xgi_video_info.TV_type ==
1003                                              TVMODE_NTSC) ? 6 : 14;
1004                                 break;
1005                         case 800:
1006                                 filter_tb = (xgi_video_info.TV_type ==
1007                                              TVMODE_NTSC) ? 7 : 15;
1008                                 break;
1009                         default:
1010                                 filter = -1;
1011                                 break;
1012                         }
1013                         xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1014
1015                         if (xgi_video_info.TV_type == TVMODE_NTSC) {
1016
1017                                 xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
1018
1019                                 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
1020
1021                                         xgifb_reg_and(XGIPART2, 0x30, 0xdf);
1022
1023                                 } else if (xgi_video_info.TV_plug
1024                                                 == TVPLUG_COMPOSITE) {
1025
1026                                         xgifb_reg_or(XGIPART2, 0x30, 0x20);
1027
1028                                         switch (xgi_video_info.video_width) {
1029                                         case 640:
1030                                                 xgifb_reg_set(XGIPART2,
1031                                                               0x35,
1032                                                               0xEB);
1033                                                 xgifb_reg_set(XGIPART2,
1034                                                               0x36,
1035                                                               0x04);
1036                                                 xgifb_reg_set(XGIPART2,
1037                                                               0x37,
1038                                                               0x25);
1039                                                 xgifb_reg_set(XGIPART2,
1040                                                               0x38,
1041                                                               0x18);
1042                                                 break;
1043                                         case 720:
1044                                                 xgifb_reg_set(XGIPART2,
1045                                                               0x35,
1046                                                               0xEE);
1047                                                 xgifb_reg_set(XGIPART2,
1048                                                               0x36,
1049                                                               0x0C);
1050                                                 xgifb_reg_set(XGIPART2,
1051                                                               0x37,
1052                                                               0x22);
1053                                                 xgifb_reg_set(XGIPART2,
1054                                                               0x38,
1055                                                               0x08);
1056                                                 break;
1057                                         case 800:
1058                                                 xgifb_reg_set(XGIPART2,
1059                                                               0x35,
1060                                                               0xEB);
1061                                                 xgifb_reg_set(XGIPART2,
1062                                                               0x36,
1063                                                               0x15);
1064                                                 xgifb_reg_set(XGIPART2,
1065                                                               0x37,
1066                                                               0x25);
1067                                                 xgifb_reg_set(XGIPART2,
1068                                                               0x38,
1069                                                               0xF6);
1070                                                 break;
1071                                         }
1072                                 }
1073
1074                         } else if (xgi_video_info.TV_type == TVMODE_PAL) {
1075
1076                                 xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
1077
1078                                 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
1079
1080                                         xgifb_reg_and(XGIPART2, 0x30, 0xDF);
1081
1082                                 } else if (xgi_video_info.TV_plug
1083                                                 == TVPLUG_COMPOSITE) {
1084
1085                                         xgifb_reg_or(XGIPART2, 0x30, 0x20);
1086
1087                                         switch (xgi_video_info.video_width) {
1088                                         case 640:
1089                                                 xgifb_reg_set(XGIPART2,
1090                                                               0x35,
1091                                                               0xF1);
1092                                                 xgifb_reg_set(XGIPART2,
1093                                                               0x36,
1094                                                               0xF7);
1095                                                 xgifb_reg_set(XGIPART2,
1096                                                               0x37,
1097                                                               0x1F);
1098                                                 xgifb_reg_set(XGIPART2,
1099                                                               0x38,
1100                                                               0x32);
1101                                                 break;
1102                                         case 720:
1103                                                 xgifb_reg_set(XGIPART2,
1104                                                               0x35,
1105                                                               0xF3);
1106                                                 xgifb_reg_set(XGIPART2,
1107                                                               0x36,
1108                                                               0x00);
1109                                                 xgifb_reg_set(XGIPART2,
1110                                                               0x37,
1111                                                               0x1D);
1112                                                 xgifb_reg_set(XGIPART2,
1113                                                               0x38,
1114                                                               0x20);
1115                                                 break;
1116                                         case 800:
1117                                                 xgifb_reg_set(XGIPART2,
1118                                                               0x35,
1119                                                               0xFC);
1120                                                 xgifb_reg_set(XGIPART2,
1121                                                               0x36,
1122                                                               0xFB);
1123                                                 xgifb_reg_set(XGIPART2,
1124                                                               0x37,
1125                                                               0x14);
1126                                                 xgifb_reg_set(XGIPART2,
1127                                                               0x38,
1128                                                               0x2A);
1129                                                 break;
1130                                         }
1131                                 }
1132                         }
1133
1134                         if ((filter >= 0) && (filter <= 7)) {
1135                                 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
1136                                         filter_tb, filter,
1137                                         XGI_TV_filter[filter_tb].
1138                                                 filter[filter][0],
1139                                         XGI_TV_filter[filter_tb].
1140                                                 filter[filter][1],
1141                                         XGI_TV_filter[filter_tb].
1142                                                 filter[filter][2],
1143                                         XGI_TV_filter[filter_tb].
1144                                                 filter[filter][3]
1145                                 );
1146                                 xgifb_reg_set(
1147                                         XGIPART2,
1148                                         0x35,
1149                                         (XGI_TV_filter[filter_tb].
1150                                                 filter[filter][0]));
1151                                 xgifb_reg_set(
1152                                         XGIPART2,
1153                                         0x36,
1154                                         (XGI_TV_filter[filter_tb].
1155                                                 filter[filter][1]));
1156                                 xgifb_reg_set(
1157                                         XGIPART2,
1158                                         0x37,
1159                                         (XGI_TV_filter[filter_tb].
1160                                                 filter[filter][2]));
1161                                 xgifb_reg_set(
1162                                         XGIPART2,
1163                                         0x38,
1164                                         (XGI_TV_filter[filter_tb].
1165                                                 filter[filter][3]));
1166                         }
1167                 }
1168         }
1169 }
1170
1171 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1172                 struct fb_info *info)
1173 {
1174
1175         unsigned int htotal = var->left_margin + var->xres + var->right_margin
1176                         + var->hsync_len;
1177         unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1178                         + var->vsync_len;
1179 #if defined(__powerpc__)
1180         u8 sr_data, cr_data;
1181 #endif
1182         unsigned int drate = 0, hrate = 0;
1183         int found_mode = 0;
1184         int old_mode;
1185         /* unsigned char reg, reg1; */
1186
1187         DEBUGPRN("Inside do_set_var");
1188         /* 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); */
1189
1190         info->var.xres_virtual = var->xres_virtual;
1191         info->var.yres_virtual = var->yres_virtual;
1192         info->var.bits_per_pixel = var->bits_per_pixel;
1193
1194         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1195                 vtotal <<= 1;
1196         else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1197                 vtotal <<= 2;
1198         else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1199                 /* vtotal <<= 1; */
1200                 /* var->yres <<= 1; */
1201         }
1202
1203         if (!htotal || !vtotal) {
1204                 DPRINTK("XGIfb: Invalid 'var' information\n");
1205                 return -EINVAL;
1206         } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1207                         var->pixclock, htotal, vtotal);
1208
1209         if (var->pixclock && htotal && vtotal) {
1210                 drate = 1000000000 / var->pixclock;
1211                 hrate = (drate * 1000) / htotal;
1212                 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1213                                 / vtotal);
1214         } else {
1215                 xgi_video_info.refresh_rate = 60;
1216         }
1217
1218         printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1219                var->xres,
1220                var->yres,
1221                var->bits_per_pixel,
1222                xgi_video_info.refresh_rate);
1223
1224         old_mode = xgifb_mode_idx;
1225         xgifb_mode_idx = 0;
1226
1227         while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1228                         && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1229                 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1230                                 && (XGIbios_mode[xgifb_mode_idx].yres
1231                                                 == var->yres)
1232                                 && (XGIbios_mode[xgifb_mode_idx].bpp
1233                                                 == var->bits_per_pixel)) {
1234                         XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1235                         found_mode = 1;
1236                         break;
1237                 }
1238                 xgifb_mode_idx++;
1239         }
1240
1241         if (found_mode)
1242                 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1243         else
1244                 xgifb_mode_idx = -1;
1245
1246         if (xgifb_mode_idx < 0) {
1247                 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n",
1248                        var->xres, var->yres, var->bits_per_pixel);
1249                 xgifb_mode_idx = old_mode;
1250                 return -EINVAL;
1251         }
1252
1253         if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1254                 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1255                 xgi_video_info.refresh_rate = 60;
1256         }
1257
1258         if (isactive) {
1259
1260                 XGIfb_pre_setmode();
1261                 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1262                         printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
1263                                XGIfb_mode_no);
1264                         return -EINVAL;
1265                 }
1266                 info->fix.line_length = ((info->var.xres_virtual
1267                                 * info->var.bits_per_pixel) >> 6);
1268
1269                 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1270
1271                 xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1272                 xgifb_reg_set(XGISR,
1273                               0x0E,
1274                               (info->fix.line_length & 0xff00) >> 8);
1275
1276                 XGIfb_post_setmode();
1277
1278                 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1279                                 XGIbios_mode[xgifb_mode_idx].xres,
1280                                 XGIbios_mode[xgifb_mode_idx].yres,
1281                                 XGIbios_mode[xgifb_mode_idx].bpp,
1282                                 xgi_video_info.refresh_rate);
1283
1284                 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1285                 xgi_video_info.video_vwidth = info->var.xres_virtual;
1286                 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1287                 xgi_video_info.video_vheight = info->var.yres_virtual;
1288                 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1289                 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1290                 xgi_video_info.video_linelength = info->var.xres_virtual
1291                                 * (xgi_video_info.video_bpp >> 3);
1292                 switch (xgi_video_info.video_bpp) {
1293                 case 8:
1294                         xgi_video_info.DstColor = 0x0000;
1295                         xgi_video_info.XGI310_AccelDepth = 0x00000000;
1296                         xgi_video_info.video_cmap_len = 256;
1297 #if defined(__powerpc__)
1298                         cr_data = xgifb_reg_get(XGICR, 0x4D);
1299                         xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
1300 #endif
1301                         break;
1302                 case 16:
1303                         xgi_video_info.DstColor = 0x8000;
1304                         xgi_video_info.XGI310_AccelDepth = 0x00010000;
1305 #if defined(__powerpc__)
1306                         cr_data = xgifb_reg_get(XGICR, 0x4D);
1307                         xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1308 #endif
1309                         xgi_video_info.video_cmap_len = 16;
1310                         break;
1311                 case 32:
1312                         xgi_video_info.DstColor = 0xC000;
1313                         xgi_video_info.XGI310_AccelDepth = 0x00020000;
1314                         xgi_video_info.video_cmap_len = 16;
1315 #if defined(__powerpc__)
1316                         cr_data = xgifb_reg_get(XGICR, 0x4D);
1317                         xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1318 #endif
1319                         break;
1320                 default:
1321                         xgi_video_info.video_cmap_len = 16;
1322                         printk(KERN_ERR "XGIfb: Unsupported depth %d",
1323                                xgi_video_info.video_bpp);
1324                         break;
1325                 }
1326         }
1327         XGIfb_bpp_to_var(var); /*update ARGB info*/
1328         DEBUGPRN("End of do_set_var");
1329
1330         dumpVGAReg();
1331         return 0;
1332 }
1333
1334 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1335 {
1336         unsigned int base;
1337
1338         /* printk("Inside pan_var"); */
1339
1340         if (var->xoffset > (var->xres_virtual - var->xres)) {
1341                 /* printk("Pan: xo: %d xv %d xr %d\n",
1342                         var->xoffset, var->xres_virtual, var->xres); */
1343                 return -EINVAL;
1344         }
1345         if (var->yoffset > (var->yres_virtual - var->yres)) {
1346                 /* printk("Pan: yo: %d yv %d yr %d\n",
1347                         var->yoffset, var->yres_virtual, var->yres); */
1348                 return -EINVAL;
1349         }
1350         base = var->yoffset * var->xres_virtual + var->xoffset;
1351
1352         /* calculate base bpp dep. */
1353         switch (var->bits_per_pixel) {
1354         case 16:
1355                 base >>= 1;
1356                 break;
1357         case 32:
1358                 break;
1359         case 8:
1360         default:
1361                 base >>= 2;
1362                 break;
1363         }
1364
1365         xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1366
1367         xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1368         xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1369         xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1370         xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
1371         xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1372
1373         if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1374                 xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1375                 xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1376                 xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1377                 xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1378                 xgifb_reg_and_or(XGIPART1,
1379                                  0x02,
1380                                  0x7F,
1381                                  ((base >> 24) & 0x01) << 7);
1382         }
1383         /* printk("End of pan_var"); */
1384         return 0;
1385 }
1386
1387 static int XGIfb_open(struct fb_info *info, int user)
1388 {
1389         return 0;
1390 }
1391
1392 static int XGIfb_release(struct fb_info *info, int user)
1393 {
1394         return 0;
1395 }
1396
1397 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1398 {
1399         int rc = 16;
1400
1401         switch (var->bits_per_pixel) {
1402         case 8:
1403                 rc = 256;
1404                 break;
1405         case 16:
1406                 rc = 16;
1407                 break;
1408         case 32:
1409                 rc = 16;
1410                 break;
1411         }
1412         return rc;
1413 }
1414
1415 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1416                 unsigned blue, unsigned transp, struct fb_info *info)
1417 {
1418         if (regno >= XGIfb_get_cmap_len(&info->var))
1419                 return 1;
1420
1421         switch (info->var.bits_per_pixel) {
1422         case 8:
1423                 outb(regno, XGIDACA);
1424                 outb((red >> 10), XGIDACD);
1425                 outb((green >> 10), XGIDACD);
1426                 outb((blue >> 10), XGIDACD);
1427                 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1428                         outb(regno, XGIDAC2A);
1429                         outb((red >> 8), XGIDAC2D);
1430                         outb((green >> 8), XGIDAC2D);
1431                         outb((blue >> 8), XGIDAC2D);
1432                 }
1433                 break;
1434         case 16:
1435                 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1436                                 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1437                                 >> 11);
1438                 break;
1439         case 32:
1440                 red >>= 8;
1441                 green >>= 8;
1442                 blue >>= 8;
1443                 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1444                                 << 8) | (blue);
1445                 break;
1446         }
1447         return 0;
1448 }
1449
1450 /* ----------- FBDev related routines for all series ---------- */
1451
1452 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1453                 struct fb_info *info)
1454 {
1455         DEBUGPRN("inside get_fix");
1456         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1457
1458         fix->smem_start = xgi_video_info.video_base;
1459
1460         fix->smem_len = xgi_video_info.video_size;
1461
1462         fix->type = FB_TYPE_PACKED_PIXELS;
1463         fix->type_aux = 0;
1464         if (xgi_video_info.video_bpp == 8)
1465                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1466         else
1467                 fix->visual = FB_VISUAL_DIRECTCOLOR;
1468         fix->xpanstep = 0;
1469         if (XGIfb_ypan)
1470                 fix->ypanstep = 1;
1471         fix->ywrapstep = 0;
1472         fix->line_length = xgi_video_info.video_linelength;
1473         fix->mmio_start = xgi_video_info.mmio_base;
1474         fix->mmio_len = xgi_video_info.mmio_size;
1475         fix->accel = FB_ACCEL_XGI_XABRE;
1476
1477         DEBUGPRN("end of get_fix");
1478         return 0;
1479 }
1480
1481 static int XGIfb_set_par(struct fb_info *info)
1482 {
1483         int err;
1484
1485         /* printk("XGIfb: inside set_par\n"); */
1486         err = XGIfb_do_set_var(&info->var, 1, info);
1487         if (err)
1488                 return err;
1489         XGIfb_get_fix(&info->fix, -1, info);
1490         /* printk("XGIfb: end of set_par\n"); */
1491         return 0;
1492 }
1493
1494 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1495 {
1496         unsigned int htotal = var->left_margin + var->xres + var->right_margin
1497                         + var->hsync_len;
1498         unsigned int vtotal = 0;
1499         unsigned int drate = 0, hrate = 0;
1500         int found_mode = 0;
1501         int refresh_rate, search_idx;
1502
1503         DEBUGPRN("Inside check_var");
1504
1505         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1506                 vtotal = var->upper_margin + var->yres + var->lower_margin
1507                                 + var->vsync_len;
1508                 vtotal <<= 1;
1509         } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1510                 vtotal = var->upper_margin + var->yres + var->lower_margin
1511                                 + var->vsync_len;
1512                 vtotal <<= 2;
1513         } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1514                 vtotal = var->upper_margin + (var->yres / 2)
1515                                 + var->lower_margin + var->vsync_len;
1516         } else
1517                 vtotal = var->upper_margin + var->yres + var->lower_margin
1518                                 + var->vsync_len;
1519
1520         if (!(htotal) || !(vtotal))
1521                 XGIFAIL("XGIfb: no valid timing data");
1522
1523         if (var->pixclock && htotal && vtotal) {
1524                 drate = 1000000000 / var->pixclock;
1525                 hrate = (drate * 1000) / htotal;
1526                 xgi_video_info.refresh_rate =
1527                         (unsigned int) (hrate * 2 / vtotal);
1528                 printk(KERN_DEBUG
1529                         "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1530                         "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1531                         __func__, var->pixclock, htotal, vtotal,
1532                         __func__, drate, hrate, xgi_video_info.refresh_rate);
1533         } else {
1534                 xgi_video_info.refresh_rate = 60;
1535         }
1536
1537         /*
1538         if ((var->pixclock) && (htotal)) {
1539                 drate = 1E12 / var->pixclock;
1540                 hrate = drate / htotal;
1541                 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1542         } else {
1543                 refresh_rate = 60;
1544         }
1545         */
1546         /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1547         if ((var->xres == 1024) && (var->yres == 600))
1548                 refresh_rate = 60;
1549
1550         search_idx = 0;
1551         while ((XGIbios_mode[search_idx].mode_no != 0) &&
1552                 (XGIbios_mode[search_idx].xres <= var->xres)) {
1553                 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1554                         (XGIbios_mode[search_idx].yres == var->yres) &&
1555                         (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1556                         if (XGIfb_validate_mode(search_idx) > 0) {
1557                                 found_mode = 1;
1558                                 break;
1559                         }
1560                 }
1561                 search_idx++;
1562         }
1563
1564         if (!found_mode) {
1565
1566                 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1567                         var->xres, var->yres, var->bits_per_pixel);
1568                 search_idx = 0;
1569                 while (XGIbios_mode[search_idx].mode_no != 0) {
1570                         if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1571                             (var->yres <= XGIbios_mode[search_idx].yres) &&
1572                             (var->bits_per_pixel ==
1573                              XGIbios_mode[search_idx].bpp)) {
1574                                 if (XGIfb_validate_mode(search_idx) > 0) {
1575                                         found_mode = 1;
1576                                         break;
1577                                 }
1578                         }
1579                         search_idx++;
1580                 }
1581                 if (found_mode) {
1582                         var->xres = XGIbios_mode[search_idx].xres;
1583                         var->yres = XGIbios_mode[search_idx].yres;
1584                         printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1585                                 var->xres, var->yres, var->bits_per_pixel);
1586
1587                 } else {
1588                         printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1589                                 var->xres, var->yres, var->bits_per_pixel);
1590                         return -EINVAL;
1591                 }
1592         }
1593
1594         /* TW: TODO: Check the refresh rate */
1595
1596         /* Adapt RGB settings */
1597         XGIfb_bpp_to_var(var);
1598
1599         /* Sanity check for offsets */
1600         if (var->xoffset < 0)
1601                 var->xoffset = 0;
1602         if (var->yoffset < 0)
1603                 var->yoffset = 0;
1604
1605         if (!XGIfb_ypan) {
1606                 if (var->xres != var->xres_virtual)
1607                         var->xres_virtual = var->xres;
1608                 if (var->yres != var->yres_virtual)
1609                         var->yres_virtual = var->yres;
1610         } /* else { */
1611                 /* TW: Now patch yres_virtual if we use panning */
1612                 /* May I do this? */
1613                 /* var->yres_virtual = xgi_video_info.heapstart /
1614                         (var->xres * (var->bits_per_pixel >> 3)); */
1615                 /* if (var->yres_virtual <= var->yres) { */
1616                 /* TW: Paranoia check */
1617                 /* var->yres_virtual = var->yres; */
1618                 /* } */
1619         /* } */
1620
1621         /* Truncate offsets to maximum if too high */
1622         if (var->xoffset > var->xres_virtual - var->xres)
1623                 var->xoffset = var->xres_virtual - var->xres - 1;
1624
1625         if (var->yoffset > var->yres_virtual - var->yres)
1626                 var->yoffset = var->yres_virtual - var->yres - 1;
1627
1628         /* Set everything else to 0 */
1629         var->red.msb_right =
1630         var->green.msb_right =
1631         var->blue.msb_right =
1632         var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1633
1634         DEBUGPRN("end of check_var");
1635         return 0;
1636 }
1637
1638 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1639                 struct fb_info *info)
1640 {
1641         int err;
1642
1643         /* printk("\nInside pan_display:\n"); */
1644
1645         if (var->xoffset > (var->xres_virtual - var->xres))
1646                 return -EINVAL;
1647         if (var->yoffset > (var->yres_virtual - var->yres))
1648                 return -EINVAL;
1649
1650         if (var->vmode & FB_VMODE_YWRAP) {
1651                 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1652                                 || var->xoffset)
1653                         return -EINVAL;
1654         } else {
1655                 if (var->xoffset + info->var.xres > info->var.xres_virtual
1656                                 || var->yoffset + info->var.yres
1657                                                 > info->var.yres_virtual)
1658                         return -EINVAL;
1659         }
1660         err = XGIfb_pan_var(var);
1661         if (err < 0)
1662                 return err;
1663
1664         info->var.xoffset = var->xoffset;
1665         info->var.yoffset = var->yoffset;
1666         if (var->vmode & FB_VMODE_YWRAP)
1667                 info->var.vmode |= FB_VMODE_YWRAP;
1668         else
1669                 info->var.vmode &= ~FB_VMODE_YWRAP;
1670
1671         /* printk("End of pan_display\n"); */
1672         return 0;
1673 }
1674
1675 static int XGIfb_blank(int blank, struct fb_info *info)
1676 {
1677         u8 reg;
1678
1679         reg = xgifb_reg_get(XGICR, 0x17);
1680
1681         if (blank > 0)
1682                 reg &= 0x7f;
1683         else
1684                 reg |= 0x80;
1685
1686         xgifb_reg_set(XGICR, 0x17, reg);
1687         xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1688         xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
1689         return 0;
1690 }
1691
1692 static struct fb_ops XGIfb_ops = {
1693         .owner = THIS_MODULE,
1694         .fb_open = XGIfb_open,
1695         .fb_release = XGIfb_release,
1696         .fb_check_var = XGIfb_check_var,
1697         .fb_set_par = XGIfb_set_par,
1698         .fb_setcolreg = XGIfb_setcolreg,
1699         .fb_pan_display = XGIfb_pan_display,
1700         .fb_blank = XGIfb_blank,
1701         .fb_fillrect = cfb_fillrect,
1702         .fb_copyarea = cfb_copyarea,
1703         .fb_imageblit = cfb_imageblit,
1704         /* .fb_mmap = XGIfb_mmap, */
1705 };
1706
1707 /* ---------------- Chip generation dependent routines ---------------- */
1708
1709 /* for XGI 315/550/650/740/330 */
1710
1711 static int XGIfb_get_dram_size(void)
1712 {
1713
1714         u8 ChannelNum, tmp;
1715         u8 reg = 0;
1716
1717         /* xorg driver sets 32MB * 1 channel */
1718         if (xgi_video_info.chip == XG27)
1719                 xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1720
1721         reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE);
1722         switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1723         case XGI_DRAM_SIZE_1MB:
1724                 xgi_video_info.video_size = 0x100000;
1725                 break;
1726         case XGI_DRAM_SIZE_2MB:
1727                 xgi_video_info.video_size = 0x200000;
1728                 break;
1729         case XGI_DRAM_SIZE_4MB:
1730                 xgi_video_info.video_size = 0x400000;
1731                 break;
1732         case XGI_DRAM_SIZE_8MB:
1733                 xgi_video_info.video_size = 0x800000;
1734                 break;
1735         case XGI_DRAM_SIZE_16MB:
1736                 xgi_video_info.video_size = 0x1000000;
1737                 break;
1738         case XGI_DRAM_SIZE_32MB:
1739                 xgi_video_info.video_size = 0x2000000;
1740                 break;
1741         case XGI_DRAM_SIZE_64MB:
1742                 xgi_video_info.video_size = 0x4000000;
1743                 break;
1744         case XGI_DRAM_SIZE_128MB:
1745                 xgi_video_info.video_size = 0x8000000;
1746                 break;
1747         case XGI_DRAM_SIZE_256MB:
1748                 xgi_video_info.video_size = 0x10000000;
1749                 break;
1750         default:
1751                 return -1;
1752         }
1753
1754         tmp = (reg & 0x0c) >> 2;
1755         switch (xgi_video_info.chip) {
1756         case XG20:
1757         case XG21:
1758         case XG27:
1759                 ChannelNum = 1;
1760                 break;
1761
1762         case XG42:
1763                 if (reg & 0x04)
1764                         ChannelNum = 2;
1765                 else
1766                         ChannelNum = 1;
1767                 break;
1768
1769         case XG45:
1770                 if (tmp == 1)
1771                         ChannelNum = 2;
1772                 else if (tmp == 2)
1773                         ChannelNum = 3;
1774                 else if (tmp == 3)
1775                         ChannelNum = 4;
1776                 else
1777                         ChannelNum = 1;
1778                 break;
1779
1780         case XG40:
1781         default:
1782                 if (tmp == 2)
1783                         ChannelNum = 2;
1784                 else if (tmp == 3)
1785                         ChannelNum = 3;
1786                 else
1787                         ChannelNum = 1;
1788                 break;
1789         }
1790
1791         xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1792         /* PLiad fixed for benchmarking and fb set */
1793         /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1794         /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1795
1796         printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
1797                reg,
1798                xgi_video_info.video_size, ChannelNum);
1799         return 0;
1800
1801 }
1802
1803 static void XGIfb_detect_VB(void)
1804 {
1805         u8 cr32, temp = 0;
1806
1807         xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1808
1809         switch (xgi_video_info.hasVB) {
1810         case HASVB_LVDS_CHRONTEL:
1811         case HASVB_CHRONTEL:
1812                 break;
1813         case HASVB_301:
1814         case HASVB_302:
1815                 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1816                 break;
1817         }
1818
1819         cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
1820
1821         if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1822                 XGIfb_crt1off = 0;
1823         else {
1824                 if (cr32 & 0x5F)
1825                         XGIfb_crt1off = 1;
1826                 else
1827                         XGIfb_crt1off = 0;
1828         }
1829
1830         if (XGIfb_crt2type != -1)
1831                 /* TW: Override with option */
1832                 xgi_video_info.disp_state = XGIfb_crt2type;
1833         else if (cr32 & XGI_VB_TV)
1834                 xgi_video_info.disp_state = DISPTYPE_TV;
1835         else if (cr32 & XGI_VB_LCD)
1836                 xgi_video_info.disp_state = DISPTYPE_LCD;
1837         else if (cr32 & XGI_VB_CRT2)
1838                 xgi_video_info.disp_state = DISPTYPE_CRT2;
1839         else
1840                 xgi_video_info.disp_state = 0;
1841
1842         if (XGIfb_tvplug != -1)
1843                 /* PR/TW: Override with option */
1844                 xgi_video_info.TV_plug = XGIfb_tvplug;
1845         else if (cr32 & XGI_VB_HIVISION) {
1846                 xgi_video_info.TV_type = TVMODE_HIVISION;
1847                 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1848         } else if (cr32 & XGI_VB_SVIDEO)
1849                 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1850         else if (cr32 & XGI_VB_COMPOSITE)
1851                 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1852         else if (cr32 & XGI_VB_SCART)
1853                 xgi_video_info.TV_plug = TVPLUG_SCART;
1854
1855         if (xgi_video_info.TV_type == 0) {
1856                 temp = xgifb_reg_get(XGICR, 0x38);
1857                 if (temp & 0x10)
1858                         xgi_video_info.TV_type = TVMODE_PAL;
1859                 else
1860                         xgi_video_info.TV_type = TVMODE_NTSC;
1861         }
1862
1863         /* TW: Copy forceCRT1 option to CRT1off if option is given */
1864         if (XGIfb_forcecrt1 != -1) {
1865                 if (XGIfb_forcecrt1)
1866                         XGIfb_crt1off = 0;
1867                 else
1868                         XGIfb_crt1off = 1;
1869         }
1870 }
1871
1872 static int XGIfb_has_VB(void)
1873 {
1874         u8 vb_chipid;
1875
1876         vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
1877         switch (vb_chipid) {
1878         case 0x01:
1879                 xgi_video_info.hasVB = HASVB_301;
1880                 break;
1881         case 0x02:
1882                 xgi_video_info.hasVB = HASVB_302;
1883                 break;
1884         default:
1885                 xgi_video_info.hasVB = HASVB_NONE;
1886                 return 0;
1887         }
1888         return 1;
1889 }
1890
1891 static void XGIfb_get_VB_type(void)
1892 {
1893         u8 reg;
1894
1895         if (!XGIfb_has_VB()) {
1896                 reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
1897                 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1898                 case XGI310_EXTERNAL_CHIP_LVDS:
1899                         xgi_video_info.hasVB = HASVB_LVDS;
1900                         break;
1901                 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1902                         xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1903                         break;
1904                 default:
1905                         break;
1906                 }
1907         }
1908 }
1909
1910 static int __init xgifb_optval(char *fullopt, int validx)
1911 {
1912         unsigned long lres;
1913
1914         if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
1915                 pr_err("xgifb: invalid value for option: %s\n", fullopt);
1916                 return 0;
1917         }
1918         return lres;
1919 }
1920
1921 static int __init XGIfb_setup(char *options)
1922 {
1923         char *this_opt;
1924
1925         if (!options || !*options)
1926                 return 0;
1927
1928         pr_info("xgifb: options: %s\n", options);
1929
1930         while ((this_opt = strsep(&options, ",")) != NULL) {
1931
1932                 if (!*this_opt)
1933                         continue;
1934
1935                 if (!strncmp(this_opt, "mode:", 5)) {
1936                         mode = this_opt + 5;
1937                 } else if (!strncmp(this_opt, "vesa:", 5)) {
1938                         vesa = xgifb_optval(this_opt, 5);
1939                 } else if (!strncmp(this_opt, "vrate:", 6)) {
1940                         xgi_video_info.refresh_rate = xgifb_optval(this_opt, 6);
1941                 } else if (!strncmp(this_opt, "rate:", 5)) {
1942                         xgi_video_info.refresh_rate = xgifb_optval(this_opt, 5);
1943                 } else if (!strncmp(this_opt, "crt1off", 7)) {
1944                         XGIfb_crt1off = 1;
1945                 } else if (!strncmp(this_opt, "filter:", 7)) {
1946                         filter = xgifb_optval(this_opt, 7);
1947                 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
1948                         XGIfb_search_crt2type(this_opt + 14);
1949                 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
1950                         XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
1951                 } else if (!strncmp(this_opt, "tvmode:", 7)) {
1952                         XGIfb_search_tvstd(this_opt + 7);
1953                 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
1954                         XGIfb_search_tvstd(this_opt + 7);
1955                 } else if (!strncmp(this_opt, "dstn", 4)) {
1956                         enable_dstn = 1;
1957                         /* TW: DSTN overrules forcecrt2type */
1958                         XGIfb_crt2type = DISPTYPE_LCD;
1959                 } else if (!strncmp(this_opt, "noypan", 6)) {
1960                         XGIfb_ypan = 0;
1961                 } else if (!strncmp(this_opt, "userom:", 7)) {
1962                         XGIfb_userom = xgifb_optval(this_opt, 7);
1963                 } else {
1964                         mode = this_opt;
1965                 }
1966         }
1967         return 0;
1968 }
1969
1970 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
1971 {
1972         void __iomem *rom_address;
1973         unsigned char *rom_copy;
1974         size_t rom_size;
1975
1976         rom_address = pci_map_rom(dev, &rom_size);
1977         if (rom_address == NULL)
1978                 return NULL;
1979
1980         rom_copy = vzalloc(XGIFB_ROM_SIZE);
1981         if (rom_copy == NULL)
1982                 goto done;
1983
1984         rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
1985         memcpy_fromio(rom_copy, rom_address, rom_size);
1986
1987 done:
1988         pci_unmap_rom(dev, rom_address);
1989         return rom_copy;
1990 }
1991
1992 static int __devinit xgifb_probe(struct pci_dev *pdev,
1993                 const struct pci_device_id *ent)
1994 {
1995         u8 reg, reg1;
1996         u8 CR48, CR38;
1997         int ret;
1998         bool xgi21_drvlcdcaplist = false;
1999
2000         memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2001         fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2002         if (!fb_info)
2003                 return -ENOMEM;
2004
2005         xgi_video_info.chip_id = pdev->device;
2006         pci_read_config_byte(pdev,
2007                              PCI_REVISION_ID,
2008                              &xgi_video_info.revision_id);
2009         XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2010
2011         xgi_video_info.pcibus = pdev->bus->number;
2012         xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2013         xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2014         xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2015         xgi_video_info.subsysdevice = pdev->subsystem_device;
2016
2017         xgi_video_info.video_base = pci_resource_start(pdev, 0);
2018         xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2019         xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2020         xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2021         XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2022         /* XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2023         printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2024                (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2025
2026         if (pci_enable_device(pdev)) {
2027                 ret = -EIO;
2028                 goto error;
2029         }
2030
2031         XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2032
2033         xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2034         reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD);
2035
2036         if (reg1 != 0xa1) { /*I/O error */
2037                 printk("\nXGIfb: I/O error!!!");
2038                 ret = -EIO;
2039                 goto error;
2040         }
2041
2042         switch (xgi_video_info.chip_id) {
2043         case PCI_DEVICE_ID_XG_20:
2044                 xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2045                 CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
2046                 if (CR48&GPIOG_READ)
2047                         xgi_video_info.chip = XG21;
2048                 else
2049                         xgi_video_info.chip = XG20;
2050                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2051                 break;
2052         case PCI_DEVICE_ID_XG_40:
2053                 xgi_video_info.chip = XG40;
2054                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2055                 break;
2056         case PCI_DEVICE_ID_XG_41:
2057                 xgi_video_info.chip = XG41;
2058                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2059                 break;
2060         case PCI_DEVICE_ID_XG_42:
2061                 xgi_video_info.chip = XG42;
2062                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2063                 break;
2064         case PCI_DEVICE_ID_XG_27:
2065                 xgi_video_info.chip = XG27;
2066                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2067                 break;
2068         default:
2069                 ret = -ENODEV;
2070                 goto error;
2071         }
2072
2073         printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
2074         XGIhw_ext.jChipType = xgi_video_info.chip;
2075
2076         if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
2077                 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
2078                 if (XGIhw_ext.pjVirtualRomBase)
2079                         printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",
2080                                XGIhw_ext.pjVirtualRomBase);
2081                 else
2082                         printk(KERN_INFO "XGIfb: Video ROM not found\n");
2083         } else {
2084                 XGIhw_ext.pjVirtualRomBase = NULL;
2085                 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2086         }
2087         XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2088
2089         if (XGIfb_get_dram_size()) {
2090                 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
2091                 ret = -ENODEV;
2092                 goto error;
2093         }
2094
2095         /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
2096         xgifb_reg_or(XGISR,
2097                      IND_XGI_PCI_ADDRESS_SET,
2098                      (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
2099         /* Enable 2D accelerator engine */
2100         xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
2101
2102         XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
2103
2104         if (!request_mem_region(xgi_video_info.video_base,
2105                                 xgi_video_info.video_size,
2106                                 "XGIfb FB")) {
2107                 printk("unable request memory size %x",
2108                        xgi_video_info.video_size);
2109                 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
2110                 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
2111                 ret = -ENODEV;
2112                 goto error;
2113         }
2114
2115         if (!request_mem_region(xgi_video_info.mmio_base,
2116                                 xgi_video_info.mmio_size,
2117                                 "XGIfb MMIO")) {
2118                 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
2119                 ret = -ENODEV;
2120                 goto error_0;
2121         }
2122
2123         xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
2124         ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
2125         xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
2126                                             xgi_video_info.mmio_size);
2127
2128         printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
2129                xgi_video_info.video_base,
2130                xgi_video_info.video_vbase,
2131                xgi_video_info.video_size / 1024);
2132
2133         printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
2134                xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
2135                xgi_video_info.mmio_size / 1024);
2136         printk("XGIfb: XGIInitNew() ...");
2137         if (XGIInitNew(&XGIhw_ext))
2138                 printk("OK\n");
2139         else
2140                 printk("Fail\n");
2141
2142         xgi_video_info.mtrr = (unsigned int) 0;
2143
2144         xgi_video_info.hasVB = HASVB_NONE;
2145         if ((xgi_video_info.chip == XG20) ||
2146             (xgi_video_info.chip == XG27)) {
2147                 xgi_video_info.hasVB = HASVB_NONE;
2148         } else if (xgi_video_info.chip == XG21) {
2149                 CR38 = xgifb_reg_get(XGICR, 0x38);
2150                 if ((CR38&0xE0) == 0xC0) {
2151                         xgi_video_info.disp_state = DISPTYPE_LCD;
2152                         if (!XGIfb_GetXG21LVDSData())
2153                                 xgi21_drvlcdcaplist = true;
2154                 } else if ((CR38&0xE0) == 0x60) {
2155                         xgi_video_info.hasVB = HASVB_CHRONTEL;
2156                 } else {
2157                         xgi_video_info.hasVB = HASVB_NONE;
2158                 }
2159         } else {
2160                 XGIfb_get_VB_type();
2161         }
2162
2163         XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
2164
2165         XGIhw_ext.ulExternalChip = 0;
2166
2167         switch (xgi_video_info.hasVB) {
2168         case HASVB_301:
2169                 reg = xgifb_reg_get(XGIPART4, 0x01);
2170                 if (reg >= 0xE0) {
2171                         XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2172                         printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2173                 } else if (reg >= 0xD0) {
2174                         XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2175                         printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
2176                 }
2177                 /* else if (reg >= 0xB0) {
2178                         XGIhw_ext.ujVBChipID = VB_CHIP_301B;
2179                         reg1 = xgifb_reg_get(XGIPART4, 0x23);
2180                         printk("XGIfb: XGI301B bridge detected\n");
2181                 } */
2182                 else {
2183                         XGIhw_ext.ujVBChipID = VB_CHIP_301;
2184                         printk("XGIfb: XGI301 bridge detected\n");
2185                 }
2186                 break;
2187         case HASVB_302:
2188                 reg = xgifb_reg_get(XGIPART4, 0x01);
2189                 if (reg >= 0xE0) {
2190                         XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2191                         printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2192                 } else if (reg >= 0xD0) {
2193                         XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2194                         printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2195                 } else if (reg >= 0xB0) {
2196                         reg1 = xgifb_reg_get(XGIPART4, 0x23);
2197
2198                         XGIhw_ext.ujVBChipID = VB_CHIP_302B;
2199
2200                 } else {
2201                         XGIhw_ext.ujVBChipID = VB_CHIP_302;
2202                         printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
2203                 }
2204                 break;
2205         case HASVB_LVDS:
2206                 XGIhw_ext.ulExternalChip = 0x1;
2207                 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
2208                 break;
2209         case HASVB_TRUMPION:
2210                 XGIhw_ext.ulExternalChip = 0x2;
2211                 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
2212                 break;
2213         case HASVB_CHRONTEL:
2214                 XGIhw_ext.ulExternalChip = 0x4;
2215                 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
2216                 break;
2217         case HASVB_LVDS_CHRONTEL:
2218                 XGIhw_ext.ulExternalChip = 0x5;
2219                 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2220                 break;
2221         default:
2222                 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
2223                 break;
2224         }
2225
2226         if (xgi_video_info.hasVB != HASVB_NONE)
2227                 XGIfb_detect_VB();
2228
2229         if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2230                 if (XGIfb_crt1off)
2231                         xgi_video_info.disp_state |= DISPMODE_SINGLE;
2232                 else
2233                         xgi_video_info.disp_state |= (DISPMODE_MIRROR |
2234                                                       DISPTYPE_CRT1);
2235         } else {
2236                 xgi_video_info.disp_state = DISPMODE_SINGLE |
2237                                             DISPTYPE_CRT1;
2238         }
2239
2240         if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2241                 if (!enable_dstn) {
2242                         reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2243                         reg &= 0x0f;
2244                         XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
2245
2246                 } else {
2247                         /* TW: FSTN/DSTN */
2248                         XGIhw_ext.ulCRT2LCDType = LCD_320x480;
2249                 }
2250         }
2251
2252         if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
2253                         (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2254                         (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
2255                 int tmp;
2256                 tmp = xgifb_reg_get(XGICR, 0x34);
2257                 if (tmp <= 0x13) {
2258                         /* Currently on LCDA?
2259                          *(Some BIOSes leave CR38) */
2260                         tmp = xgifb_reg_get(XGICR, 0x38);
2261                         if ((tmp & 0x03) == 0x03) {
2262                                 /* XGI_Pr.XGI_UseLCDA = 1; */
2263                         } else {
2264                                 /* Currently on LCDA?
2265                                  *(Some newer BIOSes set D0 in CR35) */
2266                                 tmp = xgifb_reg_get(XGICR, 0x35);
2267                                 if (tmp & 0x01) {
2268                                         /* XGI_Pr.XGI_UseLCDA = 1; */
2269                                 } else {
2270                                         tmp = xgifb_reg_get(XGICR,
2271                                                             0x30);
2272                                         if (tmp & 0x20) {
2273                                                 tmp = xgifb_reg_get(
2274                                                         XGIPART1, 0x13);
2275                                                 if (tmp & 0x04) {
2276                                                         /* XGI_Pr.XGI_UseLCDA = 1; */
2277                                                 }
2278                                         }
2279                                 }
2280                         }
2281                 }
2282
2283         }
2284
2285         if (mode)
2286                 XGIfb_search_mode(mode);
2287         else if (vesa != -1)
2288                 XGIfb_search_vesamode(vesa);
2289
2290         if (xgifb_mode_idx >= 0)
2291                 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
2292
2293         if (xgifb_mode_idx < 0) {
2294                 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) ==
2295                         DISPTYPE_LCD &&
2296                     xgi_video_info.chip == XG21)
2297                         xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
2298                 else
2299                         xgifb_mode_idx = DEFAULT_MODE;
2300         }
2301
2302         if (xgifb_mode_idx < 0) {
2303                 dev_err(&pdev->dev, "no supported video mode found\n");
2304                 goto error_1;
2305         }
2306
2307         if (xgi21_drvlcdcaplist) {
2308                 int m;
2309
2310                 for (m = 0; m < ARRAY_SIZE(XGI21_LCDCapList); m++)
2311                         if ((XGI21_LCDCapList[m].LVDSHDE ==
2312                                 XGIbios_mode[xgifb_mode_idx].xres) &&
2313                             (XGI21_LCDCapList[m].LVDSVDE ==
2314                                 XGIbios_mode[xgifb_mode_idx].yres)) {
2315                                 xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
2316                                 break;
2317                         }
2318         }
2319
2320         XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
2321
2322         /* yilin set default refresh rate */
2323         if (xgi_video_info.refresh_rate == 0)
2324                 xgi_video_info.refresh_rate = 60;
2325         if (XGIfb_search_refresh_rate(
2326                         xgi_video_info.refresh_rate) == 0) {
2327                 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
2328                 xgi_video_info.refresh_rate = 60;
2329         }
2330
2331         xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
2332         xgi_video_info.video_vwidth =
2333                 xgi_video_info.video_width =
2334                         XGIbios_mode[xgifb_mode_idx].xres;
2335         xgi_video_info.video_vheight =
2336                 xgi_video_info.video_height =
2337                         XGIbios_mode[xgifb_mode_idx].yres;
2338         xgi_video_info.org_x = xgi_video_info.org_y = 0;
2339         xgi_video_info.video_linelength =
2340                 xgi_video_info.video_width *
2341                 (xgi_video_info.video_bpp >> 3);
2342         switch (xgi_video_info.video_bpp) {
2343         case 8:
2344                 xgi_video_info.DstColor = 0x0000;
2345                 xgi_video_info.XGI310_AccelDepth = 0x00000000;
2346                 xgi_video_info.video_cmap_len = 256;
2347                 break;
2348         case 16:
2349                 xgi_video_info.DstColor = 0x8000;
2350                 xgi_video_info.XGI310_AccelDepth = 0x00010000;
2351                 xgi_video_info.video_cmap_len = 16;
2352                 break;
2353         case 32:
2354                 xgi_video_info.DstColor = 0xC000;
2355                 xgi_video_info.XGI310_AccelDepth = 0x00020000;
2356                 xgi_video_info.video_cmap_len = 16;
2357                 break;
2358         default:
2359                 xgi_video_info.video_cmap_len = 16;
2360                 printk(KERN_INFO "XGIfb: Unsupported depth %d",
2361                        xgi_video_info.video_bpp);
2362                 break;
2363         }
2364
2365         printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
2366                xgi_video_info.video_width,
2367                xgi_video_info.video_height,
2368                xgi_video_info.video_bpp,
2369                xgi_video_info.refresh_rate);
2370
2371         default_var.xres =
2372                 default_var.xres_virtual =
2373                         xgi_video_info.video_width;
2374         default_var.yres =
2375                 default_var.yres_virtual =
2376                         xgi_video_info.video_height;
2377         default_var.bits_per_pixel = xgi_video_info.video_bpp;
2378
2379         XGIfb_bpp_to_var(&default_var);
2380
2381         default_var.pixclock = (u32) (1000000000 /
2382                         XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
2383                                         XGIfb_mode_no, XGIfb_rate_idx));
2384
2385         if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
2386                 XGIfb_mode_no, XGIfb_rate_idx,
2387                 &default_var.left_margin, &default_var.right_margin,
2388                 &default_var.upper_margin, &default_var.lower_margin,
2389                 &default_var.hsync_len, &default_var.vsync_len,
2390                 &default_var.sync, &default_var.vmode)) {
2391
2392                 if ((default_var.vmode & FB_VMODE_MASK) ==
2393                     FB_VMODE_INTERLACED) {
2394                         default_var.yres <<= 1;
2395                         default_var.yres_virtual <<= 1;
2396                 } else if ((default_var.vmode & FB_VMODE_MASK) ==
2397                            FB_VMODE_DOUBLE) {
2398                         default_var.pixclock >>= 1;
2399                         default_var.yres >>= 1;
2400                         default_var.yres_virtual >>= 1;
2401                 }
2402
2403         }
2404
2405         fb_info->flags = FBINFO_FLAG_DEFAULT;
2406         fb_info->var = default_var;
2407         fb_info->fix = XGIfb_fix;
2408         fb_info->par = &xgi_video_info;
2409         fb_info->screen_base = xgi_video_info.video_vbase;
2410         fb_info->fbops = &XGIfb_ops;
2411         XGIfb_get_fix(&fb_info->fix, -1, fb_info);
2412         fb_info->pseudo_palette = pseudo_palette;
2413
2414         fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2415
2416 #ifdef CONFIG_MTRR
2417         xgi_video_info.mtrr = mtrr_add(xgi_video_info.video_base,
2418                 xgi_video_info.video_size, MTRR_TYPE_WRCOMB, 1);
2419         if (xgi_video_info.mtrr >= 0)
2420                 dev_info(&pdev->dev, "added MTRR\n");
2421 #endif
2422
2423         if (register_framebuffer(fb_info) < 0) {
2424                 ret = -EINVAL;
2425                 goto error_mtrr;
2426         }
2427
2428         dumpVGAReg();
2429
2430         return 0;
2431
2432 error_mtrr:
2433 #ifdef CONFIG_MTRR
2434         if (xgi_video_info.mtrr >= 0)
2435                 mtrr_del(xgi_video_info.mtrr, xgi_video_info.video_base,
2436                         xgi_video_info.video_size);
2437 #endif /* CONFIG_MTRR */
2438 error_1:
2439         iounmap(xgi_video_info.mmio_vbase);
2440         iounmap(xgi_video_info.video_vbase);
2441         release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2442 error_0:
2443         release_mem_region(xgi_video_info.video_base,
2444                            xgi_video_info.video_size);
2445 error:
2446         vfree(XGIhw_ext.pjVirtualRomBase);
2447         framebuffer_release(fb_info);
2448         return ret;
2449 }
2450
2451 /*****************************************************/
2452 /*                PCI DEVICE HANDLING                */
2453 /*****************************************************/
2454
2455 static void __devexit xgifb_remove(struct pci_dev *pdev)
2456 {
2457         unregister_framebuffer(fb_info);
2458 #ifdef CONFIG_MTRR
2459         if (xgi_video_info.mtrr >= 0)
2460                 mtrr_del(xgi_video_info.mtrr, xgi_video_info.video_base,
2461                         xgi_video_info.video_size);
2462 #endif /* CONFIG_MTRR */
2463         iounmap(xgi_video_info.mmio_vbase);
2464         iounmap(xgi_video_info.video_vbase);
2465         release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2466         release_mem_region(xgi_video_info.video_base,
2467                            xgi_video_info.video_size);
2468         vfree(XGIhw_ext.pjVirtualRomBase);
2469         framebuffer_release(fb_info);
2470         pci_set_drvdata(pdev, NULL);
2471 }
2472
2473 static struct pci_driver xgifb_driver = {
2474         .name = "xgifb",
2475         .id_table = xgifb_pci_table,
2476         .probe = xgifb_probe,
2477         .remove = __devexit_p(xgifb_remove)
2478 };
2479
2480 static int __init xgifb_init(void)
2481 {
2482         char *option = NULL;
2483
2484         if (fb_get_options("xgifb", &option))
2485                 return -ENODEV;
2486         XGIfb_setup(option);
2487
2488         return pci_register_driver(&xgifb_driver);
2489 }
2490
2491 module_init(xgifb_init);
2492
2493 /*****************************************************/
2494 /*                      MODULE                       */
2495 /*****************************************************/
2496
2497 #ifdef MODULE
2498
2499 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2500 MODULE_LICENSE("GPL");
2501 MODULE_AUTHOR("XGITECH , Others");
2502
2503 module_param(mode, charp, 0);
2504 module_param(vesa, int, 0);
2505 module_param(filter, int, 0);
2506
2507 MODULE_PARM_DESC(mode,
2508         "\nSelects the desired default display mode in the format XxYxDepth,\n"
2509         "eg. 1024x768x16.\n");
2510
2511 MODULE_PARM_DESC(vesa,
2512         "\nSelects the desired default display mode by VESA mode number, eg.\n"
2513         "0x117.\n");
2514
2515 MODULE_PARM_DESC(filter,
2516                 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2517                 "(Possible values 0-7, default: [no filter])\n");
2518
2519 static void __exit xgifb_remove_module(void)
2520 {
2521         pci_unregister_driver(&xgifb_driver);
2522         printk(KERN_DEBUG "xgifb: Module unloaded\n");
2523 }
2524
2525 module_exit(xgifb_remove_module);
2526
2527 #endif  /*  /MODULE  */