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