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