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