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