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