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