upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / staging / xgifb / XGI_main_26.c
1 /*
2  * XG20, XG21, XG40, XG42 frame buffer device
3  * for Linux kernels  2.5.x, 2.6.x
4  * Base on TW's sis fbdev code.
5  */
6
7 //#include <linux/config.h>
8 #include <linux/version.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/mm.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/fb.h>
20 #include <linux/console.h>
21 #include <linux/selection.h>
22 #include <linux/ioport.h>
23 #include <linux/init.h>
24 #include <linux/pci.h>
25 #include <linux/vmalloc.h>
26 #include <linux/vt_kern.h>
27 #include <linux/capability.h>
28 #include <linux/fs.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
31
32
33 #ifndef XGIFB_PAN
34 #define XGIFB_PAN
35 #endif
36
37 #include <asm/io.h>
38 #ifdef CONFIG_MTRR
39 #include <asm/mtrr.h>
40 #endif
41
42 #include "XGIfb.h"
43 #include "vgatypes.h"
44 #include "XGI_main.h"
45 #include "vb_util.h"
46
47
48 #define Index_CR_GPIO_Reg1 0x48
49 #define Index_CR_GPIO_Reg2 0x49
50 #define Index_CR_GPIO_Reg3 0x4a
51
52 #define GPIOG_EN    (1<<6)
53 #define GPIOG_WRITE (1<<6)
54 #define GPIOG_READ  (1<<1)
55 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
56
57 /* -------------------- Macro definitions ---------------------------- */
58
59 #undef XGIFBDEBUG
60
61 #ifdef XGIFBDEBUG
62 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
63 #else
64 #define DPRINTK(fmt, args...)
65 #endif
66
67 #ifdef XGIFBDEBUG
68 static void dumpVGAReg(void)
69 {
70     u8 i,reg;
71
72 outXGIIDXREG(XGISR, 0x05, 0x86);
73 /*
74 outXGIIDXREG(XGISR, 0x08, 0x4f);
75 outXGIIDXREG(XGISR, 0x0f, 0x20);
76 outXGIIDXREG(XGISR, 0x11, 0x4f);
77 outXGIIDXREG(XGISR, 0x13, 0x45);
78 outXGIIDXREG(XGISR, 0x14, 0x51);
79 outXGIIDXREG(XGISR, 0x1e, 0x41);
80 outXGIIDXREG(XGISR, 0x1f, 0x0);
81 outXGIIDXREG(XGISR, 0x20, 0xa1);
82 outXGIIDXREG(XGISR, 0x22, 0xfb);
83 outXGIIDXREG(XGISR, 0x26, 0x22);
84 outXGIIDXREG(XGISR, 0x3e, 0x07);
85 */
86
87 //outXGIIDXREG(XGICR, 0x19, 0x00);
88 //outXGIIDXREG(XGICR, 0x1a, 0x3C);
89 //outXGIIDXREG(XGICR, 0x22, 0xff);
90 //outXGIIDXREG(XGICR, 0x3D, 0x10);
91
92 //outXGIIDXREG(XGICR, 0x4a, 0xf3);
93
94 //outXGIIDXREG(XGICR, 0x57, 0x0);
95 //outXGIIDXREG(XGICR, 0x7a, 0x2c);
96
97 //outXGIIDXREG(XGICR, 0x82, 0xcc);
98 //outXGIIDXREG(XGICR, 0x8c, 0x0);
99 /*
100 outXGIIDXREG(XGICR, 0x99, 0x1);
101 outXGIIDXREG(XGICR, 0x41, 0x40);
102 */
103
104     for(i=0; i < 0x4f; i++)
105     {
106         inXGIIDXREG(XGISR, i, reg);
107         printk("\no 3c4 %x",i);
108         printk("\ni 3c5 => %x",reg);
109     }
110
111     for(i=0; i < 0xF0; i++)
112     {
113         inXGIIDXREG(XGICR, i, reg);
114         printk("\no 3d4 %x",i);
115         printk("\ni 3d5 => %x",reg);
116     }
117 /*
118
119     outXGIIDXREG(XGIPART1,0x2F,1);
120     for(i=1; i < 0x50; i++)
121     {
122         inXGIIDXREG(XGIPART1, i, reg);
123         printk("\no d004 %x",i);
124         printk("\ni d005 => %x",reg);
125     }
126
127     for(i=0; i < 0x50; i++)
128     {
129         inXGIIDXREG(XGIPART2, i, reg);
130         printk("\no d010 %x",i);
131         printk("\ni d011 => %x",reg);
132     }
133     for(i=0; i < 0x50; i++)
134     {
135         inXGIIDXREG(XGIPART3, i, reg);
136         printk("\no d012 %x",i);
137         printk("\ni d013 => %x",reg);
138     }
139     for(i=0; i < 0x50; i++)
140     {
141         inXGIIDXREG(XGIPART4, i, reg);
142         printk("\no d014 %x",i);
143         printk("\ni d015 => %x",reg);
144     }
145 */
146 }
147 #else
148 static inline void dumpVGAReg(void) {}
149 #endif
150
151 /* data for XGI components */
152 struct video_info  xgi_video_info;
153
154
155 #if 1
156 #define DEBUGPRN(x)
157 #else
158 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
159 #endif
160
161
162 /* --------------- Hardware Access Routines -------------------------- */
163
164 int
165 XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
166                           unsigned char modeno, unsigned char rateindex)
167 {
168     unsigned short ModeNo = modeno;
169     unsigned short ModeIdIndex = 0, ClockIndex = 0;
170     unsigned short RefreshRateTableIndex = 0;
171
172     /*unsigned long  temp = 0;*/
173     int    Clock;
174     XGI_Pr->ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
175     InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
176
177     RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
178
179 /*
180     temp = XGI_SearchModeID( ModeNo , &ModeIdIndex,  XGI_Pr ) ;
181     if(!temp) {
182         printk(KERN_ERR "Could not find mode %x\n", ModeNo);
183         return 65000;
184     }
185
186     RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
187     RefreshRateTableIndex += (rateindex - 1);
188
189 */
190     ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
191     if(HwDeviceExtension->jChipType < XGI_315H) {
192        ClockIndex &= 0x3F;
193     }
194     Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
195
196     return(Clock);
197 }
198
199 int
200 XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
201                          unsigned char modeno, unsigned char rateindex,
202                          u32 *left_margin, u32 *right_margin,
203                          u32 *upper_margin, u32 *lower_margin,
204                          u32 *hsync_len, u32 *vsync_len,
205                          u32 *sync, u32 *vmode)
206 {
207     unsigned short ModeNo = modeno;
208     unsigned short ModeIdIndex = 0, index = 0;
209     unsigned short RefreshRateTableIndex = 0;
210
211     unsigned short VRE, VBE, VRS, VBS, VDE, VT;
212     unsigned short HRE, HBE, HRS, HBS, HDE, HT;
213     unsigned char  sr_data, cr_data, cr_data2;
214     unsigned long cr_data3;
215     int            A, B, C, D, E, F, temp, j;
216     XGI_Pr->ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
217     InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
218   RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
219 /*
220     temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
221     if(!temp) return 0;
222
223     RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
224     RefreshRateTableIndex += (rateindex - 1);
225 */
226     index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
227
228     sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
229
230     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
231
232     /* Horizontal total */
233     HT = (cr_data & 0xff) |
234          ((unsigned short) (sr_data & 0x03) << 8);
235     A = HT + 5;
236
237     /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
238
239      Horizontal display enable end
240     HDE = (cr_data & 0xff) |
241           ((unsigned short) (sr_data & 0x0C) << 6);*/
242     HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
243     E = HDE + 1;
244
245     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
246
247     /* Horizontal retrace (=sync) start */
248     HRS = (cr_data & 0xff) |
249           ((unsigned short) (sr_data & 0xC0) << 2);
250     F = HRS - E - 3;
251
252     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
253
254     /* Horizontal blank start */
255     HBS = (cr_data & 0xff) |
256           ((unsigned short) (sr_data & 0x30) << 4);
257
258     sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
259
260     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
261
262     cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
263
264     /* Horizontal blank end */
265     HBE = (cr_data & 0x1f) |
266           ((unsigned short) (cr_data2 & 0x80) >> 2) |
267           ((unsigned short) (sr_data & 0x03) << 6);
268
269     /* Horizontal retrace (=sync) end */
270     HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
271
272     temp = HBE - ((E - 1) & 255);
273     B = (temp > 0) ? temp : (temp + 256);
274
275     temp = HRE - ((E + F + 3) & 63);
276     C = (temp > 0) ? temp : (temp + 64);
277
278     D = B - F - C;
279
280     *left_margin = D * 8;
281     *right_margin = F * 8;
282     *hsync_len = C * 8;
283
284     sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
285
286     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
287
288     cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
289
290     /* Vertical total */
291     VT = (cr_data & 0xFF) |
292          ((unsigned short) (cr_data2 & 0x01) << 8) |
293          ((unsigned short)(cr_data2 & 0x20) << 4) |
294          ((unsigned short) (sr_data & 0x01) << 10);
295     A = VT + 2;
296
297     //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
298
299     /* Vertical display enable end */
300 /*    VDE = (cr_data & 0xff) |
301           ((unsigned short) (cr_data2 & 0x02) << 7) |
302           ((unsigned short) (cr_data2 & 0x40) << 3) |
303           ((unsigned short) (sr_data & 0x02) << 9); */
304     VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes  -1;
305     E = VDE + 1;
306
307     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
308
309     /* Vertical retrace (=sync) start */
310     VRS = (cr_data & 0xff) |
311           ((unsigned short) (cr_data2 & 0x04) << 6) |
312           ((unsigned short) (cr_data2 & 0x80) << 2) |
313           ((unsigned short) (sr_data & 0x08) << 7);
314     F = VRS + 1 - E;
315
316     cr_data =  XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
317
318     cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
319
320     /* Vertical blank start */
321     VBS = (cr_data & 0xff) |
322           ((unsigned short) (cr_data2 & 0x08) << 5) |
323           ((unsigned short) (cr_data3 & 0x20) << 4) |
324           ((unsigned short) (sr_data & 0x04) << 8);
325
326     cr_data =  XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
327
328     /* Vertical blank end */
329     VBE = (cr_data & 0xff) |
330           ((unsigned short) (sr_data & 0x10) << 4);
331     temp = VBE - ((E - 1) & 511);
332     B = (temp > 0) ? temp : (temp + 512);
333
334     cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
335
336     /* Vertical retrace (=sync) end */
337     VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
338     temp = VRE - ((E + F - 1) & 31);
339     C = (temp > 0) ? temp : (temp + 32);
340
341     D = B - F - C;
342
343     *upper_margin = D;
344     *lower_margin = F;
345     *vsync_len = C;
346
347     if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
348        *sync &= ~FB_SYNC_VERT_HIGH_ACT;
349     else
350        *sync |= FB_SYNC_VERT_HIGH_ACT;
351
352     if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
353        *sync &= ~FB_SYNC_HOR_HIGH_ACT;
354     else
355        *sync |= FB_SYNC_HOR_HIGH_ACT;
356
357     *vmode = FB_VMODE_NONINTERLACED;
358     if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
359        *vmode = FB_VMODE_INTERLACED;
360     else {
361       j = 0;
362       while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
363           if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
364                           XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
365               if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
366                   *vmode = FB_VMODE_DOUBLE;
367               }
368               break;
369           }
370           j++;
371       }
372     }
373
374     return 1;
375 }
376
377
378
379
380 void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
381 {
382    XGI_Pr->RelIO = BaseAddr;
383    XGI_Pr->P3c4 = BaseAddr + 0x14;
384    XGI_Pr->P3d4 = BaseAddr + 0x24;
385    XGI_Pr->P3c0 = BaseAddr + 0x10;
386    XGI_Pr->P3ce = BaseAddr + 0x1e;
387    XGI_Pr->P3c2 = BaseAddr + 0x12;
388    XGI_Pr->P3ca = BaseAddr + 0x1a;
389    XGI_Pr->P3c6 = BaseAddr + 0x16;
390    XGI_Pr->P3c7 = BaseAddr + 0x17;
391    XGI_Pr->P3c8 = BaseAddr + 0x18;
392    XGI_Pr->P3c9 = BaseAddr + 0x19;
393    XGI_Pr->P3da = BaseAddr + 0x2A;
394    XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04;   /* Digital video interface registers (LCD) */
395    XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10;   /* 301 TV Encoder registers */
396    XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12;   /* 301 Macrovision registers */
397    XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14;   /* 301 VGA2 (and LCD) registers */
398    XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
399
400 }
401
402
403 void XGIfb_set_reg4(u16 port, unsigned long data)
404 {
405         outl((u32) (data & 0xffffffff), port);
406 }
407
408 u32 XGIfb_get_reg3(u16 port)
409 {
410         u32 data;
411
412         data = inl(port);
413         return (data);
414 }
415
416 /* ------------ Interface for init & mode switching code ------------- */
417
418 unsigned char
419 XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext,
420         unsigned long offset, unsigned long set, unsigned long *value)
421 {
422         static struct pci_dev *pdev = NULL;
423         static unsigned char init = 0, valid_pdev = 0;
424
425         if (!set)
426                 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
427         else
428                 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
429
430         if (!init) {
431                 init = 1;
432                 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
433                 if (pdev) {
434                         valid_pdev = 1;
435                         pci_dev_put(pdev);
436                 }
437         }
438
439         if (!valid_pdev) {
440                 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
441                                 xgi_video_info.chip_id);
442                 return 0;
443         }
444
445         if (set == 0)
446                 pci_read_config_dword(pdev, offset, (u32 *)value);
447         else
448                 pci_write_config_dword(pdev, offset, (u32)(*value));
449
450         return 1;
451 }
452
453 /*unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
454         unsigned long offset, unsigned long set, unsigned long *value)
455 {
456         static struct pci_dev *pdev = NULL;
457         static unsigned char init = 0, valid_pdev = 0;
458         u16 nbridge_id = 0;
459
460         if (!init) {
461                 init = 1;
462                 switch (xgi_video_info.chip) {
463                 case XGI_540:
464                         nbridge_id = PCI_DEVICE_ID_XG_540;
465                         break;
466                 case XGI_630:
467                         nbridge_id = PCI_DEVICE_ID_XG_630;
468                         break;
469                 case XGI_730:
470                         nbridge_id = PCI_DEVICE_ID_XG_730;
471                         break;
472                 case XGI_550:
473                         nbridge_id = PCI_DEVICE_ID_XG_550;
474                         break;
475                 case XGI_650:
476                         nbridge_id = PCI_DEVICE_ID_XG_650;
477                         break;
478                 case XGI_740:
479                         nbridge_id = PCI_DEVICE_ID_XG_740;
480                         break;
481                 default:
482                         nbridge_id = 0;
483                         break;
484                 }
485
486                 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
487                 if (pdev)
488                         valid_pdev = 1;
489         }
490
491         if (!valid_pdev) {
492                 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
493                                 nbridge_id);
494                 return 0;
495         }
496
497         if (set == 0)
498                 pci_read_config_dword(pdev, offset, (u32 *)value);
499         else
500                 pci_write_config_dword(pdev, offset, (u32)(*value));
501
502         return 1;
503 }
504 */
505 /* ------------------ Internal helper routines ----------------- */
506
507 static void XGIfb_search_mode(const char *name)
508 {
509         int i = 0, j = 0, l;
510
511         if(name == NULL) {
512            printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
513            xgifb_mode_idx = DEFAULT_MODE;
514            if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
515            {
516                xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
517            }
518            return;
519         }
520
521
522         if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
523            printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
524            xgifb_mode_idx = DEFAULT_MODE;
525            if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
526            {
527                xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
528            }
529            return;
530         }
531
532         while(XGIbios_mode[i].mode_no != 0) {
533                 l = min(strlen(name), strlen(XGIbios_mode[i].name));
534                 if (!strncmp(name, XGIbios_mode[i].name, l)) {
535                         xgifb_mode_idx = i;
536                         j = 1;
537                         break;
538                 }
539                 i++;
540         }
541         if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
542 }
543
544 static void XGIfb_search_vesamode(unsigned int vesamode)
545 {
546         int i = 0, j = 0;
547
548         if(vesamode == 0) {
549
550                 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
551                 xgifb_mode_idx = DEFAULT_MODE;
552                 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
553                 {
554                     xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
555                 }
556                 return;
557         }
558
559         vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
560
561         while(XGIbios_mode[i].mode_no != 0) {
562                 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
563                     (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
564                         xgifb_mode_idx = i;
565                         j = 1;
566                         break;
567                 }
568                 i++;
569         }
570         if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
571 }
572
573 int XGIfb_GetXG21LVDSData(void)
574 {
575     u8 tmp;
576     unsigned char *pData;
577     int i,j,k;
578
579     inXGIIDXREG(XGISR,0x1e,tmp);
580     outXGIIDXREG(XGISR, 0x1e, tmp|4);
581
582     pData = xgi_video_info.mmio_vbase+0x20000;
583     if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
584     {
585         i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
586         j = pData[ i-1 ] ;
587         if ( j == 0xff )
588         {
589           j = 1;
590         }
591         k = 0;
592         do
593         {
594                 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
595                 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
596                 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
597                 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
598                 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
599                 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
600                 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
601                 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
602                 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
603                 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
604                 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
605                 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
606                 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
607                 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
608                 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
609                 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
610                 i += 25;
611                 j--;
612                 k++;
613         } while ((j > 0) &&
614                  (k < (sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct))));
615         return 1;
616     }
617     return 0;
618 }
619
620 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
621 {
622
623         int found_mode = 0;
624         int XGIfb_mode_idx = 0;
625
626         found_mode = 0;
627         while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
628                (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
629         {
630                 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
631                     (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
632                     (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
633                 {
634                         XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
635                         found_mode = 1;
636                         break;
637                 }
638                 XGIfb_mode_idx++;
639         }
640         if (!found_mode)
641           XGIfb_mode_idx = 0;
642
643         return (XGIfb_mode_idx);
644 }
645
646
647 static int XGIfb_validate_mode(int myindex)
648 {
649    u16 xres, yres;
650
651     if (xgi_video_info.chip == XG21)
652     {
653         if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
654         {
655             xres = XGI21_LCDCapList[0].LVDSHDE;
656             yres = XGI21_LCDCapList[0].LVDSVDE;
657             if(XGIbios_mode[myindex].xres > xres)
658                 return(-1);
659             if(XGIbios_mode[myindex].yres > yres)
660                 return(-1);
661             if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
662             {
663               if (XGIbios_mode[myindex].bpp > 8)
664                   return(-1);
665             }
666
667        }
668        return(myindex);
669
670     }
671
672     /* FIXME: for now, all is valid on XG27 */
673     if (xgi_video_info.chip == XG27)
674             return(myindex);
675
676     if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
677         return(-1);
678
679    switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
680      case DISPTYPE_LCD:
681         switch (XGIhw_ext.ulCRT2LCDType) {
682         case LCD_640x480:
683                 xres =  640; yres =  480;  break;
684         case LCD_800x600:
685                 xres =  800; yres =  600;  break;
686         case LCD_1024x600:
687                 xres = 1024; yres =  600;  break;
688         case LCD_1024x768:
689                 xres = 1024; yres =  768;  break;
690         case LCD_1152x768:
691                 xres = 1152; yres =  768;  break;
692         case LCD_1280x960:
693                 xres = 1280; yres =  960;  break;
694         case LCD_1280x768:
695                 xres = 1280; yres =  768;  break;
696         case LCD_1280x1024:
697                 xres = 1280; yres = 1024;  break;
698         case LCD_1400x1050:
699                 xres = 1400; yres = 1050;  break;
700         case LCD_1600x1200:
701                 xres = 1600; yres = 1200;  break;
702 //      case LCD_320x480:                               // TW: FSTN
703 //              xres =  320; yres =  480;  break;
704         default:
705                 xres =    0; yres =    0;  break;
706         }
707         if(XGIbios_mode[myindex].xres > xres) {
708                 return(-1);
709         }
710         if(XGIbios_mode[myindex].yres > yres) {
711                 return(-1);
712         }
713         if((XGIhw_ext.ulExternalChip == 0x01) ||   // LVDS
714            (XGIhw_ext.ulExternalChip == 0x05))    // LVDS+Chrontel
715         {
716            switch (XGIbios_mode[myindex].xres) {
717                 case 512:
718                         if(XGIbios_mode[myindex].yres != 512) return -1;
719                         if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
720                         break;
721                 case 640:
722                         if((XGIbios_mode[myindex].yres != 400) &&
723                            (XGIbios_mode[myindex].yres != 480))
724                                 return -1;
725                         break;
726                 case 800:
727                         if(XGIbios_mode[myindex].yres != 600) return -1;
728                         break;
729                 case 1024:
730                         if((XGIbios_mode[myindex].yres != 600) &&
731                            (XGIbios_mode[myindex].yres != 768))
732                                 return -1;
733                         if((XGIbios_mode[myindex].yres == 600) &&
734                            (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
735                                 return -1;
736                         break;
737                 case 1152:
738                         if((XGIbios_mode[myindex].yres) != 768) return -1;
739                         if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
740                         break;
741                 case 1280:
742                         if((XGIbios_mode[myindex].yres != 768) &&
743                            (XGIbios_mode[myindex].yres != 1024))
744                                 return -1;
745                         if((XGIbios_mode[myindex].yres == 768) &&
746                            (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
747                                 return -1;
748                         break;
749                 case 1400:
750                         if(XGIbios_mode[myindex].yres != 1050) return -1;
751                         break;
752                 case 1600:
753                         if(XGIbios_mode[myindex].yres != 1200) return -1;
754                         break;
755                 default:
756                         return -1;
757            }
758         } else {
759            switch (XGIbios_mode[myindex].xres) {
760                 case 512:
761                         if(XGIbios_mode[myindex].yres != 512) return -1;
762                         break;
763                 case 640:
764                         if((XGIbios_mode[myindex].yres != 400) &&
765                            (XGIbios_mode[myindex].yres != 480))
766                                 return -1;
767                         break;
768                 case 800:
769                         if(XGIbios_mode[myindex].yres != 600) return -1;
770                         break;
771                 case 1024:
772                         if(XGIbios_mode[myindex].yres != 768) return -1;
773                         break;
774                 case 1280:
775                         if((XGIbios_mode[myindex].yres != 960) &&
776                            (XGIbios_mode[myindex].yres != 1024))
777                                 return -1;
778                         if(XGIbios_mode[myindex].yres == 960) {
779                             if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
780                                 return -1;
781                         }
782                         break;
783                 case 1400:
784                         if(XGIbios_mode[myindex].yres != 1050) return -1;
785                         break;
786                 case 1600:
787                         if(XGIbios_mode[myindex].yres != 1200) return -1;
788                         break;
789                 default:
790                         return -1;
791            }
792         }
793         break;
794      case DISPTYPE_TV:
795         switch (XGIbios_mode[myindex].xres) {
796         case 512:
797         case 640:
798         case 800:
799                 break;
800         case 720:
801                 if (xgi_video_info.TV_type == TVMODE_NTSC) {
802                         if (XGIbios_mode[myindex].yres != 480) {
803                                 return(-1);
804                         }
805                 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
806                         if (XGIbios_mode[myindex].yres != 576) {
807                                 return(-1);
808                         }
809                 }
810                 // TW: LVDS/CHRONTEL does not support 720
811                 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
812                                         xgi_video_info.hasVB == HASVB_CHRONTEL) {
813                                 return(-1);
814                 }
815                 break;
816         case 1024:
817                 if (xgi_video_info.TV_type == TVMODE_NTSC) {
818                         if(XGIbios_mode[myindex].bpp == 32) {
819                                return(-1);
820                         }
821                 }
822                 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
823                 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
824                                         xgi_video_info.hasVB == HASVB_CHRONTEL) {
825                     if(xgi_video_info.chip < XGI_315H) {
826                                 return(-1);
827                     }
828                 }
829                 break;
830         default:
831                 return(-1);
832         }
833         break;
834      case DISPTYPE_CRT2:
835         if(XGIbios_mode[myindex].xres > 1280) return -1;
836         break;
837      }
838      return(myindex);
839
840 }
841
842 static void XGIfb_search_crt2type(const char *name)
843 {
844         int i = 0;
845
846         if(name == NULL)
847                 return;
848
849         while(XGI_crt2type[i].type_no != -1) {
850                 if (!strcmp(name, XGI_crt2type[i].name)) {
851                         XGIfb_crt2type = XGI_crt2type[i].type_no;
852                         XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
853                         break;
854                 }
855                 i++;
856         }
857         if(XGIfb_crt2type < 0)
858                 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
859 }
860
861 static void XGIfb_search_queuemode(const char *name)
862 {
863         int i = 0;
864
865         if(name == NULL)
866                 return;
867
868         while (XGI_queuemode[i].type_no != -1) {
869                 if (!strcmp(name, XGI_queuemode[i].name)) {
870                         XGIfb_queuemode = XGI_queuemode[i].type_no;
871                         break;
872                 }
873                 i++;
874         }
875         if (XGIfb_queuemode < 0)
876                 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
877 }
878
879 static u8 XGIfb_search_refresh_rate(unsigned int rate)
880 {
881         u16 xres, yres;
882         int i = 0;
883
884         xres = XGIbios_mode[xgifb_mode_idx].xres;
885         yres = XGIbios_mode[xgifb_mode_idx].yres;
886
887         XGIfb_rate_idx = 0;
888         while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
889                 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
890                         if (XGIfb_vrate[i].refresh == rate) {
891                                 XGIfb_rate_idx = XGIfb_vrate[i].idx;
892                                 break;
893                         } else if (XGIfb_vrate[i].refresh > rate) {
894                                 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
895                                         DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
896                                                 rate, XGIfb_vrate[i].refresh);
897                                         XGIfb_rate_idx = XGIfb_vrate[i].idx;
898                                         xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
899                                 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
900                                                 && (XGIfb_vrate[i].idx != 1)) {
901                                         DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
902                                                 rate, XGIfb_vrate[i-1].refresh);
903                                         XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
904                                         xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
905                                 }
906                                 break;
907                         } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
908                                 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
909                                                 rate, XGIfb_vrate[i].refresh);
910                                 XGIfb_rate_idx = XGIfb_vrate[i].idx;
911                                 break;
912                         }
913                 }
914                 i++;
915         }
916         if (XGIfb_rate_idx > 0) {
917                 return XGIfb_rate_idx;
918         } else {
919                 printk(KERN_INFO
920                         "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
921                 return 0;
922         }
923 }
924
925 static void XGIfb_search_tvstd(const char *name)
926 {
927         int i = 0;
928
929         if(name == NULL)
930                 return;
931
932         while (XGI_tvtype[i].type_no != -1) {
933                 if (!strcmp(name, XGI_tvtype[i].name)) {
934                         XGIfb_tvmode = XGI_tvtype[i].type_no;
935                         break;
936                 }
937                 i++;
938         }
939 }
940
941 static unsigned char XGIfb_bridgeisslave(void)
942 {
943    unsigned char usScratchP1_00;
944
945    if (xgi_video_info.hasVB == HASVB_NONE)
946            return 0;
947
948    inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
949    if ((usScratchP1_00 & 0x50) == 0x10)
950            return 1;
951    else
952            return 0;
953 }
954
955 static unsigned char XGIfbcheckvretracecrt1(void)
956 {
957    unsigned char temp;
958
959    inXGIIDXREG(XGICR,0x17,temp);
960    if (!(temp & 0x80))
961            return 0;
962
963
964    inXGIIDXREG(XGISR,0x1f,temp);
965    if (temp & 0xc0)
966            return 0;
967
968    if (inXGIREG(XGIINPSTAT) & 0x08)
969            return 1;
970    else
971            return 0;
972 }
973
974 static unsigned char XGIfbcheckvretracecrt2(void)
975 {
976    unsigned char temp;
977    if (xgi_video_info.hasVB == HASVB_NONE)
978            return 0;
979    inXGIIDXREG(XGIPART1, 0x30, temp);
980    if (temp & 0x02)
981            return 0;
982    else
983            return 1;
984 }
985
986 static unsigned char XGIfb_CheckVBRetrace(void)
987 {
988    if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
989       if(XGIfb_bridgeisslave()) {
990          return(XGIfbcheckvretracecrt1());
991       } else {
992          return(XGIfbcheckvretracecrt2());
993       }
994    }
995    return(XGIfbcheckvretracecrt1());
996 }
997
998 /* ----------- FBDev related routines for all series ----------- */
999
1000
1001 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1002 {
1003         switch(var->bits_per_pixel) {
1004            case 8:
1005                 var->red.offset = var->green.offset = var->blue.offset = 0;
1006                 var->red.length = var->green.length = var->blue.length = 6;
1007                 xgi_video_info.video_cmap_len = 256;
1008                 break;
1009            case 16:
1010                 var->red.offset = 11;
1011                 var->red.length = 5;
1012                 var->green.offset = 5;
1013                 var->green.length = 6;
1014                 var->blue.offset = 0;
1015                 var->blue.length = 5;
1016                 var->transp.offset = 0;
1017                 var->transp.length = 0;
1018                 xgi_video_info.video_cmap_len = 16;
1019                 break;
1020            case 32:
1021                 var->red.offset = 16;
1022                 var->red.length = 8;
1023                 var->green.offset = 8;
1024                 var->green.length = 8;
1025                 var->blue.offset = 0;
1026                 var->blue.length = 8;
1027                 var->transp.offset = 24;
1028                 var->transp.length = 8;
1029                 xgi_video_info.video_cmap_len = 16;
1030                 break;
1031         }
1032 }
1033
1034
1035
1036 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1037                       struct fb_info *info)
1038 {
1039
1040         unsigned int htotal = var->left_margin + var->xres +
1041                 var->right_margin + var->hsync_len;
1042         unsigned int vtotal = var->upper_margin + var->yres +
1043                 var->lower_margin + var->vsync_len;
1044 #if defined(__powerpc__)
1045         u8 sr_data, cr_data;
1046 #endif
1047         unsigned int drate = 0, hrate = 0;
1048         int found_mode = 0;
1049         int old_mode;
1050 //      unsigned char reg,reg1;
1051
1052         DEBUGPRN("Inside do_set_var");
1053 //        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);
1054
1055         info->var.xres_virtual = var->xres_virtual;
1056         info->var.yres_virtual = var->yres_virtual;
1057         info->var.bits_per_pixel = var->bits_per_pixel;
1058
1059         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1060                 vtotal <<= 1;
1061         else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1062                 vtotal <<= 2;
1063         else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1064         {
1065 //              vtotal <<= 1;
1066 //              var->yres <<= 1;
1067         }
1068
1069         if(!htotal || !vtotal) {
1070                 DPRINTK("XGIfb: Invalid 'var' information\n");
1071                 return -EINVAL;
1072         }
1073         printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1074                 var->pixclock,htotal,vtotal);
1075
1076
1077
1078         if(var->pixclock && htotal && vtotal) {
1079                 drate = 1000000000 / var->pixclock;
1080                 hrate = (drate * 1000) / htotal;
1081                 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1082         } else {
1083                 xgi_video_info.refresh_rate = 60;
1084         }
1085
1086         printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1087                 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1088
1089         old_mode = xgifb_mode_idx;
1090         xgifb_mode_idx = 0;
1091
1092         while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1093                (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1094                 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1095                     (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1096                     (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1097                         XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1098                         found_mode = 1;
1099                         break;
1100                 }
1101                 xgifb_mode_idx++;
1102         }
1103
1104         if(found_mode)
1105                 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1106         else
1107                 xgifb_mode_idx = -1;
1108
1109         if(xgifb_mode_idx < 0) {
1110                 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1111                        var->yres, var->bits_per_pixel);
1112                 xgifb_mode_idx = old_mode;
1113                 return -EINVAL;
1114         }
1115
1116         if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1117                 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1118                 xgi_video_info.refresh_rate = 60;
1119         }
1120
1121         if(isactive) {
1122
1123
1124                 XGIfb_pre_setmode();
1125                 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1126                         printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1127                         return -EINVAL;
1128                 }
1129         info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1130
1131         outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1132
1133                 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1134                 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1135
1136                 XGIfb_post_setmode();
1137
1138                 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1139                         XGIbios_mode[xgifb_mode_idx].xres,
1140                         XGIbios_mode[xgifb_mode_idx].yres,
1141                         XGIbios_mode[xgifb_mode_idx].bpp,
1142                         xgi_video_info.refresh_rate);
1143
1144                 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1145                 xgi_video_info.video_vwidth = info->var.xres_virtual;
1146                 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1147                 xgi_video_info.video_vheight = info->var.yres_virtual;
1148                 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1149                 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1150                 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1151                 xgi_video_info.accel = 0;
1152                 if(XGIfb_accel) {
1153                    xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1154                 }
1155                 switch(xgi_video_info.video_bpp)
1156                 {
1157                 case 8:
1158                         xgi_video_info.DstColor = 0x0000;
1159                         xgi_video_info.XGI310_AccelDepth = 0x00000000;
1160                             xgi_video_info.video_cmap_len = 256;
1161 #if defined(__powerpc__)
1162                 inXGIIDXREG (XGICR, 0x4D, cr_data);
1163                 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1164 #endif
1165                 break;
1166                 case 16:
1167                 xgi_video_info.DstColor = 0x8000;
1168                 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1169 #if defined(__powerpc__)
1170                 inXGIIDXREG (XGICR, 0x4D, cr_data);
1171                 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1172 #endif
1173                             xgi_video_info.video_cmap_len = 16;
1174                 break;
1175                 case 32:
1176                 xgi_video_info.DstColor = 0xC000;
1177                         xgi_video_info.XGI310_AccelDepth = 0x00020000;
1178                             xgi_video_info.video_cmap_len = 16;
1179 #if defined(__powerpc__)
1180                 inXGIIDXREG (XGICR, 0x4D, cr_data);
1181                 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1182 #endif
1183                 break;
1184                     default:
1185                             xgi_video_info.video_cmap_len = 16;
1186                         printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1187                             xgi_video_info.accel = 0;
1188                             break;
1189         }
1190         }
1191         XGIfb_bpp_to_var(var); /*update ARGB info*/
1192         DEBUGPRN("End of do_set_var");
1193
1194         dumpVGAReg();
1195         return 0;
1196 }
1197
1198 #ifdef XGIFB_PAN
1199 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1200 {
1201         unsigned int base;
1202
1203 //      printk("Inside pan_var");
1204
1205         if (var->xoffset > (var->xres_virtual - var->xres)) {
1206 //              printk( "Pan: xo: %d xv %d xr %d\n",
1207 //                      var->xoffset, var->xres_virtual, var->xres);
1208                 return -EINVAL;
1209         }
1210         if(var->yoffset > (var->yres_virtual - var->yres)) {
1211 //              printk( "Pan: yo: %d yv %d yr %d\n",
1212 //                      var->yoffset, var->yres_virtual, var->yres);
1213                 return -EINVAL;
1214         }
1215         base = var->yoffset * var->xres_virtual + var->xoffset;
1216
1217         /* calculate base bpp dep. */
1218         switch(var->bits_per_pixel) {
1219         case 16:
1220                 base >>= 1;
1221                 break;
1222         case 32:
1223                 break;
1224         case 8:
1225         default:
1226                 base >>= 2;
1227                 break;
1228         }
1229
1230         outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1231
1232         outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1233         outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1234         outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1235         outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1236         setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1237
1238         if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1239                 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1240                 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1241                 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1242                 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1243                 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1244         }
1245 //      printk("End of pan_var");
1246         return 0;
1247 }
1248 #endif
1249
1250
1251 void XGI_dispinfo(struct ap_data *rec)
1252 {
1253         rec->minfo.bpp    = xgi_video_info.video_bpp;
1254         rec->minfo.xres   = xgi_video_info.video_width;
1255         rec->minfo.yres   = xgi_video_info.video_height;
1256         rec->minfo.v_xres = xgi_video_info.video_vwidth;
1257         rec->minfo.v_yres = xgi_video_info.video_vheight;
1258         rec->minfo.org_x  = xgi_video_info.org_x;
1259         rec->minfo.org_y  = xgi_video_info.org_y;
1260         rec->minfo.vrate  = xgi_video_info.refresh_rate;
1261         rec->iobase       = xgi_video_info.vga_base - 0x30;
1262         rec->mem_size     = xgi_video_info.video_size;
1263         rec->disp_state   = xgi_video_info.disp_state;
1264         rec->version      = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1265         rec->hasVB        = xgi_video_info.hasVB;
1266         rec->TV_type      = xgi_video_info.TV_type;
1267         rec->TV_plug      = xgi_video_info.TV_plug;
1268         rec->chip         = xgi_video_info.chip;
1269 }
1270
1271
1272
1273
1274 static int XGIfb_open(struct fb_info *info, int user)
1275 {
1276     return 0;
1277 }
1278
1279 static int XGIfb_release(struct fb_info *info, int user)
1280 {
1281     return 0;
1282 }
1283
1284 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1285 {
1286         int rc = 16;
1287
1288         switch(var->bits_per_pixel) {
1289         case 8:
1290                 rc = 256;
1291                 break;
1292         case 16:
1293                 rc = 16;
1294                 break;
1295         case 32:
1296                 rc = 16;
1297                 break;
1298         }
1299         return rc;
1300 }
1301
1302 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1303                            unsigned transp, struct fb_info *info)
1304 {
1305         if (regno >= XGIfb_get_cmap_len(&info->var))
1306                 return 1;
1307
1308         switch (info->var.bits_per_pixel) {
1309         case 8:
1310                 outXGIREG(XGIDACA, regno);
1311                 outXGIREG(XGIDACD, (red >> 10));
1312                 outXGIREG(XGIDACD, (green >> 10));
1313                 outXGIREG(XGIDACD, (blue >> 10));
1314                 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1315                         outXGIREG(XGIDAC2A, regno);
1316                         outXGIREG(XGIDAC2D, (red >> 8));
1317                         outXGIREG(XGIDAC2D, (green >> 8));
1318                         outXGIREG(XGIDAC2D, (blue >> 8));
1319                 }
1320                 break;
1321         case 16:
1322                 ((u32 *)(info->pseudo_palette))[regno] =
1323                     ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1324                 break;
1325         case 32:
1326                 red >>= 8;
1327                 green >>= 8;
1328                 blue >>= 8;
1329                 ((u32 *) (info->pseudo_palette))[regno] =
1330                         (red << 16) | (green << 8) | (blue);
1331                 break;
1332         }
1333         return 0;
1334 }
1335
1336 static int XGIfb_set_par(struct fb_info *info)
1337 {
1338         int err;
1339
1340 //      printk("XGIfb: inside set_par\n");
1341         if((err = XGIfb_do_set_var(&info->var, 1, info)))
1342                 return err;
1343         XGIfb_get_fix(&info->fix, -1, info);
1344 //      printk("XGIfb:end of set_par\n");
1345         return 0;
1346 }
1347
1348 static int XGIfb_check_var(struct fb_var_screeninfo *var,
1349                            struct fb_info *info)
1350 {
1351         unsigned int htotal =
1352                 var->left_margin + var->xres + var->right_margin +
1353                 var->hsync_len;
1354         unsigned int vtotal = 0;
1355         unsigned int drate = 0, hrate = 0;
1356         int found_mode = 0;
1357         int refresh_rate, search_idx;
1358
1359         DEBUGPRN("Inside check_var");
1360
1361         if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1362                 vtotal = var->upper_margin + var->yres + var->lower_margin +
1363                          var->vsync_len;
1364                 vtotal <<= 1;
1365         } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1366                 vtotal = var->upper_margin + var->yres + var->lower_margin +
1367                          var->vsync_len;
1368                 vtotal <<= 2;
1369         } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1370                 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1371                          var->vsync_len;
1372         } else  vtotal = var->upper_margin + var->yres + var->lower_margin +
1373                          var->vsync_len;
1374
1375         if(!(htotal) || !(vtotal)) {
1376                 XGIFAIL("XGIfb: no valid timing data");
1377         }
1378
1379
1380         if(var->pixclock && htotal && vtotal) {
1381                 drate = 1000000000 / var->pixclock;
1382                 hrate = (drate * 1000) / htotal;
1383                 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1384         printk(KERN_DEBUG \
1385                 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1386                 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1387                 __func__,var->pixclock, htotal, vtotal,
1388                 __func__, drate, hrate, xgi_video_info.refresh_rate);
1389         } else {
1390                 xgi_video_info.refresh_rate = 60;
1391         }
1392
1393 /*
1394         if((var->pixclock) && (htotal)) {
1395            drate = 1E12 / var->pixclock;
1396            hrate = drate / htotal;
1397            refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1398         } else refresh_rate = 60;
1399 */
1400         /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1401         if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1402
1403         search_idx = 0;
1404         while((XGIbios_mode[search_idx].mode_no != 0) &&
1405                (XGIbios_mode[search_idx].xres <= var->xres) ) {
1406             if((XGIbios_mode[search_idx].xres == var->xres) &&
1407                (XGIbios_mode[search_idx].yres == var->yres) &&
1408                     (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1409                         if(XGIfb_validate_mode(search_idx) > 0) {
1410                     found_mode = 1;
1411                     break;
1412                 }
1413             }
1414                 search_idx++;
1415         }
1416
1417         if(!found_mode) {
1418
1419                 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1420                         var->xres, var->yres, var->bits_per_pixel);
1421
1422                 search_idx = 0;
1423                 while(XGIbios_mode[search_idx].mode_no != 0) {
1424
1425                    if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1426                        (var->yres <= XGIbios_mode[search_idx].yres) &&
1427                        (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1428                           if(XGIfb_validate_mode(search_idx) > 0) {
1429                              found_mode = 1;
1430                              break;
1431                           }
1432                    }
1433                    search_idx++;
1434                 }
1435                 if(found_mode) {
1436                         var->xres = XGIbios_mode[search_idx].xres;
1437                         var->yres = XGIbios_mode[search_idx].yres;
1438                         printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1439                                 var->xres, var->yres, var->bits_per_pixel);
1440
1441                 } else {
1442                         printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1443                                 var->xres, var->yres, var->bits_per_pixel);
1444                         return -EINVAL;
1445                 }
1446         }
1447
1448         /* TW: TODO: Check the refresh rate */
1449
1450         /* Adapt RGB settings */
1451         XGIfb_bpp_to_var(var);
1452
1453         /* Sanity check for offsets */
1454         if (var->xoffset < 0)
1455                 var->xoffset = 0;
1456         if (var->yoffset < 0)
1457                 var->yoffset = 0;
1458
1459
1460         if(!XGIfb_ypan) {
1461                 if(var->xres != var->xres_virtual)
1462                          var->xres_virtual = var->xres;
1463                 if(var->yres != var->yres_virtual)
1464                         var->yres_virtual = var->yres;
1465         }/* else {
1466            // TW: Now patch yres_virtual if we use panning
1467            // May I do this?
1468            var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1469             if(var->yres_virtual <= var->yres) {
1470                 // TW: Paranoia check
1471                 var->yres_virtual = var->yres;
1472             }
1473         }*/
1474
1475         /* Truncate offsets to maximum if too high */
1476         if (var->xoffset > var->xres_virtual - var->xres)
1477                 var->xoffset = var->xres_virtual - var->xres - 1;
1478
1479         if (var->yoffset > var->yres_virtual - var->yres)
1480                 var->yoffset = var->yres_virtual - var->yres - 1;
1481
1482         /* Set everything else to 0 */
1483         var->red.msb_right =
1484             var->green.msb_right =
1485             var->blue.msb_right =
1486             var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1487
1488         DEBUGPRN("end of check_var");
1489         return 0;
1490 }
1491
1492 #ifdef XGIFB_PAN
1493 static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1494                                  struct fb_info* info)
1495 {
1496         int err;
1497
1498 //      printk("\nInside pan_display:");
1499
1500         if (var->xoffset > (var->xres_virtual - var->xres))
1501                 return -EINVAL;
1502         if (var->yoffset > (var->yres_virtual - var->yres))
1503                 return -EINVAL;
1504
1505         if (var->vmode & FB_VMODE_YWRAP) {
1506                 if (var->yoffset < 0
1507                     || var->yoffset >= info->var.yres_virtual
1508                     || var->xoffset) return -EINVAL;
1509         } else {
1510                 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1511                     var->yoffset + info->var.yres > info->var.yres_virtual)
1512                         return -EINVAL;
1513         }
1514
1515         if((err = XGIfb_pan_var(var)) < 0) return err;
1516
1517         info->var.xoffset = var->xoffset;
1518         info->var.yoffset = var->yoffset;
1519         if (var->vmode & FB_VMODE_YWRAP)
1520                 info->var.vmode |= FB_VMODE_YWRAP;
1521         else
1522                 info->var.vmode &= ~FB_VMODE_YWRAP;
1523
1524 //      printk(" End of pan_display");
1525         return 0;
1526 }
1527 #endif
1528
1529
1530 static int XGIfb_blank(int blank, struct fb_info *info)
1531 {
1532         u8 reg;
1533
1534         inXGIIDXREG(XGICR, 0x17, reg);
1535
1536         if(blank > 0)
1537                 reg &= 0x7f;
1538         else
1539                 reg |= 0x80;
1540
1541         outXGIIDXREG(XGICR, 0x17, reg);
1542         outXGIIDXREG(XGISR, 0x00, 0x01);    /* Synchronous Reset */
1543         outXGIIDXREG(XGISR, 0x00, 0x03);    /* End Reset */
1544         return(0);
1545 }
1546
1547
1548 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1549                             unsigned long arg)
1550 {
1551         DEBUGPRN("inside ioctl");
1552         switch (cmd) {
1553            case FBIO_ALLOC:
1554                 if (!capable(CAP_SYS_RAWIO))
1555                         return -EPERM;
1556                 XGI_malloc((struct XGI_memreq *) arg);
1557                 break;
1558            case FBIO_FREE:
1559                 if (!capable(CAP_SYS_RAWIO))
1560                         return -EPERM;
1561                 XGI_free(*(unsigned long *) arg);
1562                 break;
1563            case FBIOGET_HWCINFO:
1564                 {
1565                         unsigned long *hwc_offset = (unsigned long *) arg;
1566
1567                         if (XGIfb_caps & HW_CURSOR_CAP)
1568                                 *hwc_offset = XGIfb_hwcursor_vbase -
1569                                     (unsigned long) xgi_video_info.video_vbase;
1570                         else
1571                                 *hwc_offset = 0;
1572
1573                         break;
1574                 }
1575            case FBIOPUT_MODEINFO:
1576                 {
1577                         struct mode_info *x = (struct mode_info *)arg;
1578
1579                         xgi_video_info.video_bpp        = x->bpp;
1580                         xgi_video_info.video_width      = x->xres;
1581                         xgi_video_info.video_height     = x->yres;
1582                         xgi_video_info.video_vwidth     = x->v_xres;
1583                         xgi_video_info.video_vheight    = x->v_yres;
1584                         xgi_video_info.org_x            = x->org_x;
1585                         xgi_video_info.org_y            = x->org_y;
1586                         xgi_video_info.refresh_rate     = x->vrate;
1587                         xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1588                         switch(xgi_video_info.video_bpp) {
1589                         case 8:
1590                                 xgi_video_info.DstColor = 0x0000;
1591                                 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1592                                 xgi_video_info.video_cmap_len = 256;
1593                                 break;
1594                         case 16:
1595                                 xgi_video_info.DstColor = 0x8000;
1596                                 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1597                                 xgi_video_info.video_cmap_len = 16;
1598                                 break;
1599                         case 32:
1600                                 xgi_video_info.DstColor = 0xC000;
1601                                 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1602                                 xgi_video_info.video_cmap_len = 16;
1603                                 break;
1604                         default:
1605                                 xgi_video_info.video_cmap_len = 16;
1606                                 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1607                                 xgi_video_info.accel = 0;
1608                                 break;
1609                         }
1610
1611                         break;
1612                 }
1613            case FBIOGET_DISPINFO:
1614                 XGI_dispinfo((struct ap_data *)arg);
1615                 break;
1616            case XGIFB_GET_INFO:  /* TW: New for communication with X driver */
1617                 {
1618                         struct XGIfb_info *x = (struct XGIfb_info *)arg;
1619
1620                         //x->XGIfb_id = XGIFB_ID;
1621                         x->XGIfb_version = VER_MAJOR;
1622                         x->XGIfb_revision = VER_MINOR;
1623                         x->XGIfb_patchlevel = VER_LEVEL;
1624                         x->chip_id = xgi_video_info.chip_id;
1625                         x->memory = xgi_video_info.video_size / 1024;
1626                         x->heapstart = xgi_video_info.heapstart / 1024;
1627                         x->fbvidmode = XGIfb_mode_no;
1628                         x->XGIfb_caps = XGIfb_caps;
1629                         x->XGIfb_tqlen = 512; /* yet unused */
1630                         x->XGIfb_pcibus = xgi_video_info.pcibus;
1631                         x->XGIfb_pcislot = xgi_video_info.pcislot;
1632                         x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1633                         x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1634                         x->XGIfb_lcda = XGIfb_detectedlcda;
1635                         break;
1636                 }
1637            case XGIFB_GET_VBRSTATUS:
1638                 {
1639                         unsigned long *vbrstatus = (unsigned long *) arg;
1640                         if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1641                         else                       *vbrstatus = 0;
1642                 }
1643            default:
1644                 return -EINVAL;
1645         }
1646         DEBUGPRN("end of ioctl");
1647         return 0;
1648
1649 }
1650
1651
1652
1653 /* ----------- FBDev related routines for all series ---------- */
1654
1655 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1656                          struct fb_info *info)
1657 {
1658         DEBUGPRN("inside get_fix");
1659         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1660
1661         strcpy(fix->id, myid);
1662
1663         fix->smem_start = xgi_video_info.video_base;
1664
1665         fix->smem_len = xgi_video_info.video_size;
1666
1667
1668 /*        if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1669             if (xgi_video_info.video_size > 0x1000000) {
1670                 fix->smem_len = 0xD00000;
1671             } else if (xgi_video_info.video_size > 0x800000)
1672                 fix->smem_len = 0x800000;
1673             else
1674                 fix->smem_len = 0x400000;
1675         } else
1676                 fix->smem_len = XGIfb_mem * 1024;
1677 */
1678         fix->type        = video_type;
1679         fix->type_aux    = 0;
1680         if(xgi_video_info.video_bpp == 8)
1681                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1682         else
1683                 fix->visual = FB_VISUAL_DIRECTCOLOR;
1684         fix->xpanstep    = 0;
1685 #ifdef XGIFB_PAN
1686         if(XGIfb_ypan)   fix->ypanstep = 1;
1687 #endif
1688         fix->ywrapstep   = 0;
1689         fix->line_length = xgi_video_info.video_linelength;
1690         fix->mmio_start  = xgi_video_info.mmio_base;
1691         fix->mmio_len    = XGIfb_mmio_size;
1692     if(xgi_video_info.chip >= XG40)
1693            fix->accel    = FB_ACCEL_XGI_XABRE;
1694         else
1695            fix->accel    = FB_ACCEL_XGI_GLAMOUR_2;
1696
1697
1698         DEBUGPRN("end of get_fix");
1699         return 0;
1700 }
1701
1702
1703 static struct fb_ops XGIfb_ops = {
1704         .owner        = THIS_MODULE,
1705         .fb_open      = XGIfb_open,
1706         .fb_release   = XGIfb_release,
1707         .fb_check_var = XGIfb_check_var,
1708         .fb_set_par   = XGIfb_set_par,
1709         .fb_setcolreg = XGIfb_setcolreg,
1710 #ifdef XGIFB_PAN
1711         .fb_pan_display = XGIfb_pan_display,
1712 #endif
1713         .fb_blank     = XGIfb_blank,
1714         .fb_fillrect  = fbcon_XGI_fillrect,
1715         .fb_copyarea  = fbcon_XGI_copyarea,
1716         .fb_imageblit = cfb_imageblit,
1717         .fb_sync      = fbcon_XGI_sync,
1718         .fb_ioctl     = XGIfb_ioctl,
1719 //      .fb_mmap      = XGIfb_mmap,
1720 };
1721
1722 /* ---------------- Chip generation dependent routines ---------------- */
1723
1724
1725 /* for XGI 315/550/650/740/330 */
1726
1727 static int XGIfb_get_dram_size(void)
1728 {
1729
1730         u8  ChannelNum,tmp;
1731         u8  reg = 0;
1732
1733         /* xorg driver sets 32MB * 1 channel */
1734         if (xgi_video_info.chip == XG27)
1735                 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1736
1737                 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1738                 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1739                    case XGI_DRAM_SIZE_1MB:
1740                         xgi_video_info.video_size = 0x100000;
1741                         break;
1742                    case XGI_DRAM_SIZE_2MB:
1743                         xgi_video_info.video_size = 0x200000;
1744                         break;
1745                    case XGI_DRAM_SIZE_4MB:
1746                         xgi_video_info.video_size = 0x400000;
1747                         break;
1748                    case XGI_DRAM_SIZE_8MB:
1749                         xgi_video_info.video_size = 0x800000;
1750                         break;
1751                    case XGI_DRAM_SIZE_16MB:
1752                         xgi_video_info.video_size = 0x1000000;
1753                         break;
1754                    case XGI_DRAM_SIZE_32MB:
1755                         xgi_video_info.video_size = 0x2000000;
1756                         break;
1757                    case XGI_DRAM_SIZE_64MB:
1758                         xgi_video_info.video_size = 0x4000000;
1759                         break;
1760                    case XGI_DRAM_SIZE_128MB:
1761                         xgi_video_info.video_size = 0x8000000;
1762                         break;
1763                    case XGI_DRAM_SIZE_256MB:
1764                         xgi_video_info.video_size = 0x10000000;
1765                         break;
1766                    default:
1767                         return -1;
1768                 }
1769
1770                 tmp = (reg & 0x0c) >> 2;
1771                 switch(xgi_video_info.chip)
1772                 {
1773                     case XG20:
1774                     case XG21:
1775                     case XG27:
1776                         ChannelNum = 1;
1777                         break;
1778
1779                     case XG42:
1780                         if(reg & 0x04)
1781                             ChannelNum = 2;
1782                         else
1783                             ChannelNum = 1;
1784                         break;
1785
1786                     case XG45:
1787                         if(tmp == 1)
1788                     ChannelNum = 2;
1789                 else
1790                 if(tmp == 2)
1791                     ChannelNum = 3;
1792                 else
1793                 if(tmp == 3)
1794                     ChannelNum = 4;
1795                 else
1796                     ChannelNum = 1;
1797                         break;
1798
1799                     case XG40:
1800                     default:
1801                 if(tmp == 2)
1802                     ChannelNum = 2;
1803                 else
1804                 if(tmp == 3)
1805                     ChannelNum = 3;
1806                 else
1807                     ChannelNum = 1;
1808                         break;
1809                 }
1810
1811
1812                 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1813                 //PLiad fixed for benchmarking and fb set
1814                 //xgi_video_info.video_size = 0x200000;//1024x768x16
1815                 //xgi_video_info.video_size = 0x1000000;//benchmark
1816
1817                 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1818                 return 0;
1819
1820 }
1821
1822 static void XGIfb_detect_VB(void)
1823 {
1824         u8 cr32, temp=0;
1825
1826         xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1827
1828         switch(xgi_video_info.hasVB) {
1829           case HASVB_LVDS_CHRONTEL:
1830           case HASVB_CHRONTEL:
1831              break;
1832           case HASVB_301:
1833           case HASVB_302:
1834 //           XGI_Sense30x(); //Yi-Lin TV Sense?
1835              break;
1836         }
1837
1838         inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1839
1840         if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1841                 XGIfb_crt1off = 0;
1842         else {
1843                 if (cr32 & 0x5F)
1844                         XGIfb_crt1off = 1;
1845                 else
1846                         XGIfb_crt1off = 0;
1847         }
1848
1849         if (XGIfb_crt2type != -1)
1850                 /* TW: Override with option */
1851                 xgi_video_info.disp_state = XGIfb_crt2type;
1852         else if (cr32 & XGI_VB_TV)
1853                 xgi_video_info.disp_state = DISPTYPE_TV;
1854         else if (cr32 & XGI_VB_LCD)
1855                 xgi_video_info.disp_state = DISPTYPE_LCD;
1856         else if (cr32 & XGI_VB_CRT2)
1857                 xgi_video_info.disp_state = DISPTYPE_CRT2;
1858         else
1859                 xgi_video_info.disp_state = 0;
1860
1861         if(XGIfb_tvplug != -1)
1862                 /* PR/TW: Override with option */
1863                 xgi_video_info.TV_plug = XGIfb_tvplug;
1864         else if (cr32 & XGI_VB_HIVISION) {
1865                 xgi_video_info.TV_type = TVMODE_HIVISION;
1866                 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1867         }
1868         else if (cr32 & XGI_VB_SVIDEO)
1869                 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1870         else if (cr32 & XGI_VB_COMPOSITE)
1871                 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1872         else if (cr32 & XGI_VB_SCART)
1873                 xgi_video_info.TV_plug = TVPLUG_SCART;
1874
1875         if(xgi_video_info.TV_type == 0) {
1876             /* TW: PAL/NTSC changed for 650 */
1877             if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1878
1879                 inXGIIDXREG(XGICR, 0x38, temp);
1880                 if(temp & 0x10)
1881                         xgi_video_info.TV_type = TVMODE_PAL;
1882                 else
1883                         xgi_video_info.TV_type = TVMODE_NTSC;
1884
1885             } else {
1886
1887                 inXGIIDXREG(XGICR, 0x79, temp);
1888                 if(temp & 0x20)
1889                         xgi_video_info.TV_type = TVMODE_PAL;
1890                 else
1891                         xgi_video_info.TV_type = TVMODE_NTSC;
1892             }
1893         }
1894
1895         /* TW: Copy forceCRT1 option to CRT1off if option is given */
1896         if (XGIfb_forcecrt1 != -1) {
1897                 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1898                 else                 XGIfb_crt1off = 1;
1899         }
1900 }
1901
1902 static void XGIfb_get_VB_type(void)
1903 {
1904         u8 reg;
1905
1906         if (!XGIfb_has_VB()) {
1907                 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1908                 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1909                    case XGI310_EXTERNAL_CHIP_LVDS:
1910                         xgi_video_info.hasVB = HASVB_LVDS;
1911                         break;
1912                    case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1913                         xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1914                         break;
1915                    default:
1916                         break;
1917                 }
1918         }
1919 }
1920
1921
1922 static int XGIfb_has_VB(void)
1923 {
1924         u8 vb_chipid;
1925
1926         inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1927         switch (vb_chipid) {
1928            case 0x01:
1929                 xgi_video_info.hasVB = HASVB_301;
1930                 break;
1931            case 0x02:
1932                 xgi_video_info.hasVB = HASVB_302;
1933                 break;
1934            default:
1935                 xgi_video_info.hasVB = HASVB_NONE;
1936                 return 0;
1937         }
1938         return 1;
1939 }
1940
1941
1942
1943 /* ------------------ Sensing routines ------------------ */
1944
1945 /* TW: Determine and detect attached devices on XGI30x */
1946 int
1947 XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1948 {
1949     int temp,i;
1950
1951     outXGIIDXREG(XGIPART4,0x11,tempbl);
1952     temp = tempbh | tempcl;
1953     setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
1954     for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
1955     tempch &= 0x7f;
1956     inXGIIDXREG(XGIPART4,0x03,temp);
1957     temp ^= 0x0e;
1958     temp &= tempch;
1959     return(temp);
1960 }
1961
1962 void
1963 XGI_Sense30x(void)
1964 {
1965   u8 backupP4_0d;
1966   u8 testsvhs_tempbl, testsvhs_tempbh;
1967   u8 testsvhs_tempcl, testsvhs_tempch;
1968   u8 testcvbs_tempbl, testcvbs_tempbh;
1969   u8 testcvbs_tempcl, testcvbs_tempch;
1970   u8 testvga2_tempbl, testvga2_tempbh;
1971   u8 testvga2_tempcl, testvga2_tempch;
1972   int myflag, result;
1973
1974   inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
1975   outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
1976
1977
1978
1979         testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
1980         testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
1981         testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
1982         if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
1983            (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
1984               testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
1985               testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
1986               testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
1987               if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
1988                  XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
1989                  testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
1990                  testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
1991                  testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
1992               }
1993         }
1994         if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
1995            XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
1996            inXGIIDXREG(XGIPART4,0x01,myflag);
1997            if(myflag & 0x04) {
1998               testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
1999               testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
2000               testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2001            }
2002         }
2003         if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2004            (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2005            testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2006            testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2007            testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2008            testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2009         } else {
2010            testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2011            testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2012            testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2013         }
2014
2015
2016     if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2017         result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2018                             testvga2_tempcl, testvga2_tempch);
2019         if(result) {
2020                 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2021                 orXGIIDXREG(XGICR, 0x32, 0x10);
2022         }
2023     }
2024
2025     result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2026                         testsvhs_tempcl, testsvhs_tempch);
2027     if(result) {
2028         printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2029         /* TW: So we can be sure that there IS a SVHS output */
2030         xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2031         orXGIIDXREG(XGICR, 0x32, 0x02);
2032     }
2033
2034     if(!result) {
2035         result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2036                             testcvbs_tempcl, testcvbs_tempch);
2037         if(result) {
2038             printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2039             /* TW: So we can be sure that there IS a CVBS output */
2040             xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2041             orXGIIDXREG(XGICR, 0x32, 0x01);
2042         }
2043     }
2044     XGIDoSense(0, 0, 0, 0);
2045
2046     outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2047 }
2048
2049
2050
2051 /* ------------------------ Heap routines -------------------------- */
2052
2053 static int XGIfb_heap_init(void)
2054 {
2055         XGI_OH *poh;
2056         u8 temp=0;
2057
2058         int            agp_enabled = 1;
2059         u32            agp_size;
2060         unsigned long *cmdq_baseport = 0;
2061         unsigned long *read_port = 0;
2062         unsigned long *write_port = 0;
2063         XGI_CMDTYPE    cmd_type;
2064 #ifndef AGPOFF
2065         struct agp_kern_info  *agp_info;
2066         struct agp_memory     *agp;
2067         u32            agp_phys;
2068 #endif
2069
2070 /* TW: The heap start is either set manually using the "mem" parameter, or
2071  *     defaults as follows:
2072  *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
2073  *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
2074  *     -) If 4MB or less is available, let it start at 4MB.
2075  *     This is for avoiding a clash with X driver which uses the beginning
2076  *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2077  *     in XF86Config-4.
2078  *     The heap start can also be specified by parameter "mem" when starting the XGIfb
2079  *     driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2080  */
2081      if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2082         if (xgi_video_info.video_size > 0x1000000) {
2083                 xgi_video_info.heapstart = 0xD00000;
2084         } else if (xgi_video_info.video_size > 0x800000) {
2085                 xgi_video_info.heapstart = 0x800000;
2086         } else {
2087                 xgi_video_info.heapstart = 0x400000;
2088         }
2089      } else {
2090            xgi_video_info.heapstart = XGIfb_mem * 1024;
2091      }
2092      XGIfb_heap_start =
2093                (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2094      printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2095                                         (int)(xgi_video_info.heapstart / 1024));
2096
2097      XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2098      XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2099
2100
2101
2102         /* TW: Now initialize the 310 series' command queue mode.
2103          * On 310/325, there are three queue modes available which
2104          * are chosen by setting bits 7:5 in SR26:
2105          * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2106          *    track of the queue, the FIFO, command parsing and so
2107          *    on. This is the one comparable to the 300 series.
2108          * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2109          *    have to do queue management himself. Register 0x85c4 will
2110          *    hold the location of the next free queue slot, 0x85c8
2111          *    is the "queue read pointer" whose way of working is
2112          *    unknown to me. Anyway, this mode would require a
2113          *    translation of the MMIO commands to some kind of
2114          *    accelerator assembly and writing these commands
2115          *    to the memory location pointed to by 0x85c4.
2116          *    We will not use this, as nobody knows how this
2117          *    "assembly" works, and as it would require a complete
2118          *    re-write of the accelerator code.
2119          * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2120          *    queue in AGP memory space.
2121          *
2122          * SR26 bit 4 is called "Bypass H/W queue".
2123          * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2124          * SR26 bit 0 resets the queue
2125          * Size of queue memory is encoded in bits 3:2 like this:
2126          *    00  (0x00)  512K
2127          *    01  (0x04)  1M
2128          *    10  (0x08)  2M
2129          *    11  (0x0C)  4M
2130          * The queue location is to be written to 0x85C0.
2131          *
2132          */
2133         cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2134         write_port    = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2135         read_port     = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2136
2137         DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2138
2139         agp_size  = COMMAND_QUEUE_AREA_SIZE;
2140
2141 #ifndef AGPOFF
2142         if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2143                 agp_info = vmalloc(sizeof(*agp_info));
2144                 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2145                 agp_copy_info(agp_info);
2146
2147                 agp_backend_acquire();
2148
2149                 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2150                                           AGP_NORMAL_MEMORY);
2151                 if (agp == NULL) {
2152                         DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2153                         agp_enabled = 0;
2154                 } else {
2155                         if (agp_bind_memory(agp, agp->pg_start) != 0) {
2156                                 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2157                                 /* TODO: Free AGP memory here */
2158                                 agp_enabled = 0;
2159                         } else {
2160                                 agp_enable(0);
2161                         }
2162                 }
2163         }
2164 #else
2165         agp_enabled = 0;
2166 #endif
2167
2168         /* TW: Now select the queue mode */
2169
2170         if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2171                 cmd_type = AGP_CMD_QUEUE;
2172                 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2173 /*      } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
2174         } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2175                 cmd_type = VM_CMD_QUEUE;
2176                 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2177         } else {
2178                 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2179                 cmd_type = MMIO_CMD;
2180         }
2181
2182         switch (agp_size) {
2183            case 0x80000:
2184                 temp = XGI_CMD_QUEUE_SIZE_512k;
2185                 break;
2186            case 0x100000:
2187                 temp = XGI_CMD_QUEUE_SIZE_1M;
2188                 break;
2189            case 0x200000:
2190                 temp = XGI_CMD_QUEUE_SIZE_2M;
2191                 break;
2192            case 0x400000:
2193                 temp = XGI_CMD_QUEUE_SIZE_4M;
2194                 break;
2195         }
2196
2197         switch (cmd_type) {
2198            case AGP_CMD_QUEUE:
2199 #ifndef AGPOFF
2200                 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2201                         agp_info->aper_base, agp->physical, agp_size/1024);
2202
2203                 agp_phys = agp_info->aper_base + agp->physical;
2204
2205                 outXGIIDXREG(XGICR,  IND_XGI_AGP_IO_PAD, 0);
2206                 outXGIIDXREG(XGICR,  IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2207
2208                 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2209
2210                 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2211
2212                 *write_port = *read_port;
2213
2214                 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2215                 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2216
2217                 *cmdq_baseport = agp_phys;
2218
2219                 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2220 #endif
2221                 break;
2222
2223            case VM_CMD_QUEUE:
2224                 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2225                 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2226
2227                 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2228
2229                 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2230
2231                 *write_port = *read_port;
2232
2233                 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2234                 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2235
2236                 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2237
2238                 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2239
2240                 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2241                         *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2242                 break;
2243
2244            default:  /* MMIO */
2245
2246 //              printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2247                 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2248                  * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2249                  * enough. Reserve memory in any way.
2250                  */
2251 // FIXME                XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2252 // FIXME                XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2253 // FIXME
2254 // FIXME                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2255 // FIXME                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2256 // FIXME
2257 // FIXME                *write_port = *read_port;
2258 // FIXME
2259 // FIXME                /* TW: Set Auto_Correction bit */
2260 // FIXME                temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2261 // FIXME                // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2262 // FIXME
2263 // FIXME                *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2264 // FIXME
2265 // FIXME                XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2266 // FIXME
2267 // FIXME                DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2268 // FIXME                        *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2269                 break;
2270         }
2271
2272
2273
2274
2275      /* TW: Now reserve memory for the HWCursor. It is always located at the very
2276             top of the videoRAM, right below the TB memory area (if used). */
2277      if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2278                 XGIfb_heap_end -= XGIfb_hwcursor_size;
2279                 XGIfb_heap_size -= XGIfb_hwcursor_size;
2280                 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2281
2282                 XGIfb_caps |= HW_CURSOR_CAP;
2283
2284                 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2285                         XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2286      }
2287
2288      XGIfb_heap.poha_chain = NULL;
2289      XGIfb_heap.poh_freelist = NULL;
2290
2291      poh = XGIfb_poh_new_node();
2292
2293      if(poh == NULL)  return 1;
2294
2295      poh->poh_next = &XGIfb_heap.oh_free;
2296      poh->poh_prev = &XGIfb_heap.oh_free;
2297      poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2298      poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2299
2300      DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2301                 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2302                 (unsigned int) poh->size / 1024);
2303
2304      DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2305                 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2306
2307      XGIfb_heap.oh_free.poh_next = poh;
2308      XGIfb_heap.oh_free.poh_prev = poh;
2309      XGIfb_heap.oh_free.size = 0;
2310      XGIfb_heap.max_freesize = poh->size;
2311
2312      XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2313      XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2314      XGIfb_heap.oh_used.size = SENTINEL;
2315
2316      return 0;
2317 }
2318
2319 static XGI_OH *XGIfb_poh_new_node(void)
2320 {
2321         int           i;
2322         unsigned long cOhs;
2323         XGI_OHALLOC   *poha;
2324         XGI_OH        *poh;
2325
2326         if (XGIfb_heap.poh_freelist == NULL) {
2327                 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2328                 if(!poha) return NULL;
2329
2330                 poha->poha_next = XGIfb_heap.poha_chain;
2331                 XGIfb_heap.poha_chain = poha;
2332
2333                 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2334
2335                 poh = &poha->aoh[0];
2336                 for (i = cOhs - 1; i != 0; i--) {
2337                         poh->poh_next = poh + 1;
2338                         poh = poh + 1;
2339                 }
2340
2341                 poh->poh_next = NULL;
2342                 XGIfb_heap.poh_freelist = &poha->aoh[0];
2343         }
2344
2345         poh = XGIfb_heap.poh_freelist;
2346         XGIfb_heap.poh_freelist = poh->poh_next;
2347
2348         return (poh);
2349 }
2350
2351 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2352 {
2353         XGI_OH *pohThis;
2354         XGI_OH *pohRoot;
2355         int     bAllocated = 0;
2356
2357         if (size > XGIfb_heap.max_freesize) {
2358                 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2359                         (unsigned int) size / 1024);
2360                 return (NULL);
2361         }
2362
2363         pohThis = XGIfb_heap.oh_free.poh_next;
2364
2365         while (pohThis != &XGIfb_heap.oh_free) {
2366                 if (size <= pohThis->size) {
2367                         bAllocated = 1;
2368                         break;
2369                 }
2370                 pohThis = pohThis->poh_next;
2371         }
2372
2373         if (!bAllocated) {
2374                 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2375                         (unsigned int) size / 1024);
2376                 return (NULL);
2377         }
2378
2379         if (size == pohThis->size) {
2380                 pohRoot = pohThis;
2381                 XGIfb_delete_node(pohThis);
2382         } else {
2383                 pohRoot = XGIfb_poh_new_node();
2384
2385                 if (pohRoot == NULL) {
2386                         return (NULL);
2387                 }
2388
2389                 pohRoot->offset = pohThis->offset;
2390                 pohRoot->size = size;
2391
2392                 pohThis->offset += size;
2393                 pohThis->size -= size;
2394         }
2395
2396         XGIfb_heap.max_freesize -= size;
2397
2398         pohThis = &XGIfb_heap.oh_used;
2399         XGIfb_insert_node(pohThis, pohRoot);
2400
2401         return (pohRoot);
2402 }
2403
2404 static void XGIfb_delete_node(XGI_OH *poh)
2405 {
2406         XGI_OH *poh_prev;
2407         XGI_OH *poh_next;
2408
2409         poh_prev = poh->poh_prev;
2410         poh_next = poh->poh_next;
2411
2412         poh_prev->poh_next = poh_next;
2413         poh_next->poh_prev = poh_prev;
2414
2415 }
2416
2417 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2418 {
2419         XGI_OH *pohTemp;
2420
2421         pohTemp = pohList->poh_next;
2422
2423         pohList->poh_next = poh;
2424         pohTemp->poh_prev = poh;
2425
2426         poh->poh_prev = pohList;
2427         poh->poh_next = pohTemp;
2428 }
2429
2430 static XGI_OH *XGIfb_poh_free(unsigned long base)
2431 {
2432         XGI_OH *pohThis;
2433         XGI_OH *poh_freed;
2434         XGI_OH *poh_prev;
2435         XGI_OH *poh_next;
2436         unsigned long ulUpper;
2437         unsigned long ulLower;
2438         int foundNode = 0;
2439
2440         poh_freed = XGIfb_heap.oh_used.poh_next;
2441
2442         while(poh_freed != &XGIfb_heap.oh_used) {
2443                 if(poh_freed->offset == base) {
2444                         foundNode = 1;
2445                         break;
2446                 }
2447
2448                 poh_freed = poh_freed->poh_next;
2449         }
2450
2451         if (!foundNode)  return (NULL);
2452
2453         XGIfb_heap.max_freesize += poh_freed->size;
2454
2455         poh_prev = poh_next = NULL;
2456         ulUpper = poh_freed->offset + poh_freed->size;
2457         ulLower = poh_freed->offset;
2458
2459         pohThis = XGIfb_heap.oh_free.poh_next;
2460
2461         while (pohThis != &XGIfb_heap.oh_free) {
2462                 if (pohThis->offset == ulUpper) {
2463                         poh_next = pohThis;
2464                 }
2465                         else if ((pohThis->offset + pohThis->size) ==
2466                                  ulLower) {
2467                         poh_prev = pohThis;
2468                 }
2469                 pohThis = pohThis->poh_next;
2470         }
2471
2472         XGIfb_delete_node(poh_freed);
2473
2474         if (poh_prev && poh_next) {
2475                 poh_prev->size += (poh_freed->size + poh_next->size);
2476                 XGIfb_delete_node(poh_next);
2477                 XGIfb_free_node(poh_freed);
2478                 XGIfb_free_node(poh_next);
2479                 return (poh_prev);
2480         }
2481
2482         if (poh_prev) {
2483                 poh_prev->size += poh_freed->size;
2484                 XGIfb_free_node(poh_freed);
2485                 return (poh_prev);
2486         }
2487
2488         if (poh_next) {
2489                 poh_next->size += poh_freed->size;
2490                 poh_next->offset = poh_freed->offset;
2491                 XGIfb_free_node(poh_freed);
2492                 return (poh_next);
2493         }
2494
2495         XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2496
2497         return (poh_freed);
2498 }
2499
2500 static void XGIfb_free_node(XGI_OH *poh)
2501 {
2502         if(poh == NULL) return;
2503
2504         poh->poh_next = XGIfb_heap.poh_freelist;
2505         XGIfb_heap.poh_freelist = poh;
2506
2507 }
2508
2509 void XGI_malloc(struct XGI_memreq *req)
2510 {
2511         XGI_OH *poh;
2512
2513         poh = XGIfb_poh_allocate(req->size);
2514
2515         if(poh == NULL) {
2516                 req->offset = 0;
2517                 req->size = 0;
2518                 DPRINTK("XGIfb: Video RAM allocation failed\n");
2519         } else {
2520                 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2521                         (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2522
2523                 req->offset = poh->offset;
2524                 req->size = poh->size;
2525         }
2526
2527 }
2528
2529 void XGI_free(unsigned long base)
2530 {
2531         XGI_OH *poh;
2532
2533         poh = XGIfb_poh_free(base);
2534
2535         if(poh == NULL) {
2536                 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2537                         (unsigned int) base);
2538         }
2539 }
2540
2541 /* --------------------- SetMode routines ------------------------- */
2542
2543 static void XGIfb_pre_setmode(void)
2544 {
2545         u8 cr30 = 0, cr31 = 0;
2546
2547         inXGIIDXREG(XGICR, 0x31, cr31);
2548         cr31 &= ~0x60;
2549
2550         switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2551            case DISPTYPE_CRT2:
2552                 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2553                 cr31 |= XGI_DRIVER_MODE;
2554                 break;
2555            case DISPTYPE_LCD:
2556                 cr30  = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2557                 cr31 |= XGI_DRIVER_MODE;
2558                 break;
2559            case DISPTYPE_TV:
2560                 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2561                         cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2562                 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2563                         cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2564                 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2565                         cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2566                 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2567                         cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2568                 cr31 |= XGI_DRIVER_MODE;
2569
2570                 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2571                         cr31 |= 0x01;
2572                 else
2573                         cr31 &= ~0x01;
2574                 break;
2575            default:     /* disable CRT2 */
2576                 cr30 = 0x00;
2577                 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2578         }
2579
2580         outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2581         outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2582         outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2583
2584         if(xgi_video_info.accel) XGIfb_syncaccel();
2585
2586
2587 }
2588
2589 static void XGIfb_post_setmode(void)
2590 {
2591         u8 reg;
2592         unsigned char doit = 1;
2593 /*      outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2594         outXGIIDXREG(XGICR,0x13,0x00);
2595         setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2596 *test**/
2597         if (xgi_video_info.video_bpp == 8) {
2598                 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2599                 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2600                         doit = 0;
2601                 }
2602                 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2603                 if  (xgi_video_info.disp_state & DISPTYPE_LCD)  {
2604                         doit = 0;
2605                 }
2606         }
2607
2608         /* TW: We can't switch off CRT1 if bridge is in slave mode */
2609         if(xgi_video_info.hasVB != HASVB_NONE) {
2610                 inXGIIDXREG(XGIPART1, 0x00, reg);
2611
2612
2613                 if ((reg & 0x50) == 0x10)
2614                         doit = 0;
2615
2616
2617         } else
2618                 XGIfb_crt1off = 0;
2619
2620         inXGIIDXREG(XGICR, 0x17, reg);
2621         if ((XGIfb_crt1off) && (doit))
2622                 reg &= ~0x80;
2623         else
2624                 reg |= 0x80;
2625         outXGIIDXREG(XGICR, 0x17, reg);
2626
2627         andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2628
2629         if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2630
2631            inXGIIDXREG(XGIPART4, 0x01, reg);
2632
2633            if(reg < 0xB0) {             /* Set filter for XGI301 */
2634
2635                 switch (xgi_video_info.video_width) {
2636                    case 320:
2637                         filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2638                         break;
2639                    case 640:
2640                         filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2641                         break;
2642                    case 720:
2643                         filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2644                         break;
2645                    case 800:
2646                         filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2647                         break;
2648                    default:
2649                         filter = -1;
2650                         break;
2651                 }
2652
2653                 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2654
2655                 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2656
2657                         andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2658
2659                         if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2660
2661                                 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2662
2663                         } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2664
2665                                 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2666
2667                                 switch (xgi_video_info.video_width) {
2668                                 case 640:
2669                                         outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2670                                         outXGIIDXREG(XGIPART2, 0x36, 0x04);
2671                                         outXGIIDXREG(XGIPART2, 0x37, 0x25);
2672                                         outXGIIDXREG(XGIPART2, 0x38, 0x18);
2673                                         break;
2674                                 case 720:
2675                                         outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2676                                         outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2677                                         outXGIIDXREG(XGIPART2, 0x37, 0x22);
2678                                         outXGIIDXREG(XGIPART2, 0x38, 0x08);
2679                                         break;
2680                                 case 800:
2681                                         outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2682                                         outXGIIDXREG(XGIPART2, 0x36, 0x15);
2683                                         outXGIIDXREG(XGIPART2, 0x37, 0x25);
2684                                         outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2685                                         break;
2686                                 }
2687                         }
2688
2689                 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2690
2691                         andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2692
2693                         if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2694
2695                                 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2696
2697                         } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2698
2699                                 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2700
2701                                 switch (xgi_video_info.video_width) {
2702                                 case 640:
2703                                         outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2704                                         outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2705                                         outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2706                                         outXGIIDXREG(XGIPART2, 0x38, 0x32);
2707                                         break;
2708                                 case 720:
2709                                         outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2710                                         outXGIIDXREG(XGIPART2, 0x36, 0x00);
2711                                         outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2712                                         outXGIIDXREG(XGIPART2, 0x38, 0x20);
2713                                         break;
2714                                 case 800:
2715                                         outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2716                                         outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2717                                         outXGIIDXREG(XGIPART2, 0x37, 0x14);
2718                                         outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2719                                         break;
2720                                 }
2721                         }
2722                 }
2723
2724                 if ((filter >= 0) && (filter <=7)) {
2725                         DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2726                                 XGI_TV_filter[filter_tb].filter[filter][0],
2727                                 XGI_TV_filter[filter_tb].filter[filter][1],
2728                                 XGI_TV_filter[filter_tb].filter[filter][2],
2729                                 XGI_TV_filter[filter_tb].filter[filter][3]
2730                         );
2731                         outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2732                         outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2733                         outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2734                         outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2735                 }
2736
2737              }
2738
2739         }
2740
2741 }
2742
2743 #ifndef MODULE
2744 XGIINITSTATIC int __init XGIfb_setup(char *options)
2745 {
2746         char *this_opt;
2747
2748
2749
2750         xgi_video_info.refresh_rate = 0;
2751
2752         printk(KERN_INFO "XGIfb: Options %s\n", options);
2753
2754         if (!options || !*options)
2755                 return 0;
2756
2757         while((this_opt = strsep(&options, ",")) != NULL) {
2758
2759                 if (!*this_opt) continue;
2760
2761                 if (!strncmp(this_opt, "mode:", 5)) {
2762                         XGIfb_search_mode(this_opt + 5);
2763                 } else if (!strncmp(this_opt, "vesa:", 5)) {
2764                         XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2765                 } else if (!strncmp(this_opt, "mode:", 5)) {
2766                         XGIfb_search_mode(this_opt + 5);
2767                 } else if (!strncmp(this_opt, "vesa:", 5)) {
2768                         XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2769                 } else if (!strncmp(this_opt, "vrate:", 6)) {
2770                         xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2771                 } else if (!strncmp(this_opt, "rate:", 5)) {
2772                         xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2773                 } else if (!strncmp(this_opt, "off", 3)) {
2774                         XGIfb_off = 1;
2775                 } else if (!strncmp(this_opt, "crt1off", 7)) {
2776                         XGIfb_crt1off = 1;
2777                 } else if (!strncmp(this_opt, "filter:", 7)) {
2778                         filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2779                 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2780                         XGIfb_search_crt2type(this_opt + 14);
2781                 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2782                         XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2783                 } else if (!strncmp(this_opt, "tvmode:",7)) {
2784                         XGIfb_search_tvstd(this_opt + 7);
2785                 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2786                         XGIfb_search_tvstd(this_opt + 7);
2787                 } else if (!strncmp(this_opt, "mem:",4)) {
2788                         XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2789                 } else if (!strncmp(this_opt, "dstn", 4)) {
2790                         enable_dstn = 1;
2791                         /* TW: DSTN overrules forcecrt2type */
2792                         XGIfb_crt2type = DISPTYPE_LCD;
2793                 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2794                         XGIfb_search_queuemode(this_opt + 10);
2795                 } else if (!strncmp(this_opt, "pdc:", 4)) {
2796                         XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2797                         if(XGIfb_pdc & ~0x3c) {
2798                            printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2799                            XGIfb_pdc = 0;
2800                         }
2801                 } else if (!strncmp(this_opt, "noaccel", 7)) {
2802                         XGIfb_accel = 0;
2803                 } else if (!strncmp(this_opt, "noypan", 6)) {
2804                         XGIfb_ypan = 0;
2805                 } else if (!strncmp(this_opt, "userom:", 7)) {
2806                         XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2807 //              } else if (!strncmp(this_opt, "useoem:", 7)) {
2808 //                      XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2809                 } else {
2810                         XGIfb_search_mode(this_opt);
2811 //                      printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2812                 }
2813
2814                 /* TW: Acceleration only with MMIO mode */
2815                 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2816                         XGIfb_ypan = 0;
2817                         XGIfb_accel = 0;
2818                 }
2819                 /* TW: Panning only with acceleration */
2820                 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2821
2822         }
2823         printk("\nxgifb: outa xgifb_setup 3450");
2824         return 0;
2825 }
2826 #endif
2827
2828 static unsigned char VBIOS_BUF[65535];
2829
2830 unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
2831 {
2832     u32 rom_size      = 0;
2833     u32 rom_address   = 0;
2834     int j;
2835
2836     /*  Get the size of the expansion rom */
2837     pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2838     pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2839     if ((rom_size & 0x01) == 0)
2840     {
2841                 printk("No ROM\n");
2842                 return NULL;
2843     }
2844
2845     rom_size &= 0xFFFFF800;
2846     rom_size = (~rom_size)+1;
2847
2848     rom_address = pci_resource_start(dev, 0);
2849     if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2850     {
2851                 printk("No suitable rom address found\n"); return NULL;
2852     }
2853
2854     printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2855
2856     /*  Map ROM */
2857     pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2858
2859     /* memcpy(copy_address, rom_address, rom_size); */
2860     {
2861                 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2862
2863                 unsigned char *from = (unsigned char *)virt_addr;
2864                 unsigned char *to = (unsigned char *)copy_address;
2865                 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2866         }
2867
2868         pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2869
2870     printk("Copy is done\n");
2871
2872         return copy_address;
2873 }
2874
2875 int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2876 {
2877         u16 reg16;
2878         u8  reg, reg1;
2879         u8 CR48,CR38;
2880         if (XGIfb_off)
2881                 return -ENXIO;
2882
2883         XGIfb_registered = 0;
2884
2885         memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2886           fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2887           if(!fb_info) return -ENOMEM;
2888
2889         xgi_video_info.chip_id = pdev->device;
2890           pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2891           pci_read_config_word(pdev, PCI_COMMAND, &reg16);
2892           XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2893           XGIvga_enabled = reg16 & 0x01;
2894
2895           xgi_video_info.pcibus = pdev->bus->number;
2896           xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2897           xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2898           xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2899           xgi_video_info.subsysdevice = pdev->subsystem_device;
2900
2901           xgi_video_info.video_base = pci_resource_start(pdev, 0);
2902           xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2903           XGIfb_mmio_size =  pci_resource_len(pdev, 1);
2904           xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2905           XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2906           //XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2907           printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2908                  (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2909
2910           if (pci_enable_device(pdev))
2911                   return -EIO;
2912
2913     XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2914
2915     outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2916     inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2917
2918     if(reg1 != 0xa1) /*I/O error */
2919     {
2920          printk("\nXGIfb: I/O error!!!");
2921          return  -EIO;
2922     }
2923
2924         switch (xgi_video_info.chip_id) {
2925            case PCI_DEVICE_ID_XG_20:
2926                 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2927                 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2928                 if (CR48&GPIOG_READ)
2929                         xgi_video_info.chip = XG21;
2930                 else
2931                         xgi_video_info.chip = XG20;
2932                 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2933                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2934                 break;
2935             case PCI_DEVICE_ID_XG_40:
2936                 xgi_video_info.chip = XG40;
2937                 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2938                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2939                 break;
2940             case PCI_DEVICE_ID_XG_41:
2941                 xgi_video_info.chip = XG41;
2942                 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2943                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2944                 break;
2945             case PCI_DEVICE_ID_XG_42:
2946                 xgi_video_info.chip = XG42;
2947                 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2948                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2949                 break;
2950             case PCI_DEVICE_ID_XG_27:
2951                 xgi_video_info.chip = XG27;
2952                 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2953                 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2954                 break;
2955            default:
2956                 return -ENODEV;
2957         }
2958
2959         printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
2960          XGIhw_ext.jChipType = xgi_video_info.chip;
2961
2962                 switch (xgi_video_info.chip) {
2963                    case XG40:
2964                    case XG41:
2965                    case XG42:
2966                    case XG45:
2967                    case XG20:
2968                    case XG21:
2969                    case XG27:
2970                            XGIhw_ext.bIntegratedMMEnabled = 1;
2971                         break;
2972
2973                    default:
2974                         break;
2975                 }
2976
2977
2978           XGIhw_ext.pDevice = NULL;
2979           if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
2980           {
2981               XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
2982
2983               if(XGIhw_ext.pjVirtualRomBase)
2984                         printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
2985                 else
2986                         printk(KERN_INFO "XGIfb: Video ROM not found\n");
2987     } else {
2988                 XGIhw_ext.pjVirtualRomBase = NULL;
2989                 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2990     }
2991           XGIhw_ext.pjCustomizedROMImage = NULL;
2992           XGIhw_ext.bSkipDramSizing = 0;
2993           XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2994 //      XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
2995           strcpy(XGIhw_ext.szVBIOSVer, "0.84");
2996
2997
2998     XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
2999           if (XGIhw_ext.pSR == NULL)
3000           {
3001                     printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3002                     return -ENODEV;
3003           }
3004           XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3005
3006           XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
3007           if (XGIhw_ext.pCR == NULL)
3008           {
3009               vfree(XGIhw_ext.pSR);
3010                     printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3011                     return -ENODEV;
3012           }
3013           XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3014
3015
3016
3017
3018         if (!XGIvga_enabled)
3019         {
3020                         /* Mapping Max FB Size for 315 Init */
3021             XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3022             if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3023             {
3024 #ifdef LINUXBIOS
3025                 printk("XGIfb: XGIInit() ...");
3026                 /* XGIInitNewt for LINUXBIOS only */
3027                 if(XGIInitNew(&XGIhw_ext))
3028                 {
3029                         printk("OK\n");
3030                 }
3031                 else
3032                 {
3033                     printk("Fail\n");
3034                 }
3035 #endif
3036
3037                 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3038
3039
3040             }
3041         }
3042 #ifdef LINUXBIOS
3043         else
3044         {
3045             XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3046             if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3047             {
3048
3049                 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3050
3051                 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3052                 // Set SR13 ,14 temporarily for UDtech
3053                 outXGIIDXREG(XGISR, 0x13, 0x45);
3054                 outXGIIDXREG(XGISR, 0x14, 0x51);
3055
3056
3057             }
3058         }
3059 #endif
3060         if (XGIfb_get_dram_size())
3061         {
3062             vfree(XGIhw_ext.pSR);
3063             vfree(XGIhw_ext.pCR);
3064             printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3065             return -ENODEV;
3066         }
3067
3068
3069
3070           if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3071           {
3072                /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
3073         orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3074          /* Enable 2D accelerator engine */
3075         orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3076     }
3077
3078           XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3079
3080           if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3081           {         printk("unable request memory size %x",xgi_video_info.video_size);
3082                     printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3083                     printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3084                     vfree(XGIhw_ext.pSR);
3085                     vfree(XGIhw_ext.pCR);
3086                     return -ENODEV;
3087           }
3088
3089           if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3090           {
3091                     printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3092                     release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3093                     vfree(XGIhw_ext.pSR);
3094                     vfree(XGIhw_ext.pCR);
3095                     return -ENODEV;
3096           }
3097
3098           xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3099                 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3100           xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3101
3102           printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3103               xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3104
3105           printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3106               xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3107           printk("XGIfb: XGIInitNew() ...");
3108           if(XGIInitNew(&XGIhw_ext))
3109           {
3110                   printk("OK\n");
3111           }
3112           else
3113           {
3114                 printk("Fail\n");
3115           }
3116
3117           if(XGIfb_heap_init())
3118           {
3119                     printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3120           }
3121
3122
3123           xgi_video_info.mtrr = (unsigned int) 0;
3124
3125           if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3126           {
3127                   xgi_video_info.hasVB = HASVB_NONE;
3128         if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3129               xgi_video_info.hasVB = HASVB_NONE;
3130         else if(xgi_video_info.chip == XG21) {
3131             inXGIIDXREG(XGICR,0x38,CR38);
3132             if ((CR38&0xE0) == 0xC0) {
3133                     xgi_video_info.disp_state = DISPTYPE_LCD;
3134                     if (!XGIfb_GetXG21LVDSData()) {
3135                             int m;
3136                             for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
3137                                     if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3138                                         (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3139                                                 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3140                                     }
3141                             }
3142                     }
3143             }
3144             else if ((CR38&0xE0) == 0x60)
3145                 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3146             else
3147                 xgi_video_info.hasVB = HASVB_NONE;
3148         }
3149         else
3150                     XGIfb_get_VB_type();
3151
3152                     XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3153
3154                     XGIhw_ext.ulExternalChip = 0;
3155
3156                 switch (xgi_video_info.hasVB) {
3157                 case HASVB_301:
3158                         inXGIIDXREG(XGIPART4, 0x01, reg);
3159                         if (reg >= 0xE0) {
3160                                 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3161                                 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3162                         } else if (reg >= 0xD0) {
3163                                 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3164                                 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3165                         }
3166                         /* else if (reg >= 0xB0) {
3167                                 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3168                                 inXGIIDXREG(XGIPART4,0x23,reg1);
3169                                printk("XGIfb: XGI301B bridge detected\n");
3170                         }*/
3171                         else {
3172                                 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3173                                 printk("XGIfb: XGI301 bridge detected\n");
3174                         }
3175                         break;
3176                 case HASVB_302:
3177                         inXGIIDXREG(XGIPART4, 0x01, reg);
3178                         if (reg >= 0xE0) {
3179                                 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3180                                 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3181                         } else if (reg >= 0xD0) {
3182                                 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3183                                 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3184                         } else if (reg >= 0xB0) {
3185                                 inXGIIDXREG(XGIPART4,0x23,reg1);
3186
3187                                 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3188
3189                         } else {
3190                                 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3191                                 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3192                         }
3193                         break;
3194                 case HASVB_LVDS:
3195                         XGIhw_ext.ulExternalChip = 0x1;
3196                         printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3197                         break;
3198                 case HASVB_TRUMPION:
3199                         XGIhw_ext.ulExternalChip = 0x2;
3200                         printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3201                         break;
3202                 case HASVB_CHRONTEL:
3203                         XGIhw_ext.ulExternalChip = 0x4;
3204                         printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3205                         break;
3206                 case HASVB_LVDS_CHRONTEL:
3207                         XGIhw_ext.ulExternalChip = 0x5;
3208                         printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3209                         break;
3210                 default:
3211                         printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3212                         break;
3213                 }
3214
3215                 if (xgi_video_info.hasVB != HASVB_NONE) {
3216                     XGIfb_detect_VB();
3217     }
3218
3219                 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3220                         if (XGIfb_crt1off)
3221                                 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3222                         else
3223                                 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3224                 } else {
3225                         xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3226                 }
3227
3228                 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3229                     if (!enable_dstn) {
3230                         inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3231                             reg &= 0x0f;
3232                             XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3233
3234                     } else {
3235                         // TW: FSTN/DSTN
3236                         XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3237                     }
3238                 }
3239
3240                 XGIfb_detectedpdc = 0;
3241
3242                 XGIfb_detectedlcda = 0xff;
3243 #ifndef LINUXBIOS
3244
3245                 /* TW: Try to find about LCDA */
3246
3247         if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3248                (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3249                (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3250             {
3251                int tmp;
3252                inXGIIDXREG(XGICR,0x34,tmp);
3253                if(tmp <= 0x13)
3254                {
3255                   // Currently on LCDA? (Some BIOSes leave CR38)
3256                   inXGIIDXREG(XGICR,0x38,tmp);
3257                       if((tmp & 0x03) == 0x03)
3258                       {
3259 /*                        XGI_Pr.XGI_UseLCDA = 1; */
3260                       }else
3261                       {
3262                      //  Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3263                          inXGIIDXREG(XGICR,0x35,tmp);
3264                          if(tmp & 0x01)
3265                          {
3266 /*                            XGI_Pr.XGI_UseLCDA = 1; */
3267                            }else
3268                            {
3269                                inXGIIDXREG(XGICR,0x30,tmp);
3270                                if(tmp & 0x20)
3271                                {
3272                                    inXGIIDXREG(XGIPART1,0x13,tmp);
3273                                        if(tmp & 0x04)
3274                                        {
3275 /*                                      XGI_Pr.XGI_UseLCDA = 1; */
3276                                        }
3277                                }
3278                            }
3279                         }
3280                  }
3281
3282         }
3283
3284
3285 #endif
3286
3287                 if (xgifb_mode_idx >= 0)
3288                         xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3289
3290                 if (xgifb_mode_idx < 0) {
3291                         switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3292                            case DISPTYPE_LCD:
3293                                 xgifb_mode_idx = DEFAULT_LCDMODE;
3294                                 if (xgi_video_info.chip == XG21)
3295                                 {
3296                                     xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3297                                 }
3298                                 break;
3299                            case DISPTYPE_TV:
3300                                 xgifb_mode_idx = DEFAULT_TVMODE;
3301                                 break;
3302                            default:
3303                                 xgifb_mode_idx = DEFAULT_MODE;
3304                                 break;
3305                         }
3306                 }
3307
3308                 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3309
3310
3311                 if( xgi_video_info.refresh_rate == 0)
3312                     xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3313                 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3314                 {
3315                     XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3316                     xgi_video_info.refresh_rate = 60;
3317                 }
3318
3319                 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3320                 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3321                 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3322                 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3323                 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3324                 switch(xgi_video_info.video_bpp) {
3325                 case 8:
3326                         xgi_video_info.DstColor = 0x0000;
3327                         xgi_video_info.XGI310_AccelDepth = 0x00000000;
3328                         xgi_video_info.video_cmap_len = 256;
3329                         break;
3330                 case 16:
3331                         xgi_video_info.DstColor = 0x8000;
3332                         xgi_video_info.XGI310_AccelDepth = 0x00010000;
3333                         xgi_video_info.video_cmap_len = 16;
3334                         break;
3335                 case 32:
3336                         xgi_video_info.DstColor = 0xC000;
3337                         xgi_video_info.XGI310_AccelDepth = 0x00020000;
3338                         xgi_video_info.video_cmap_len = 16;
3339                         break;
3340                 default:
3341                         xgi_video_info.video_cmap_len = 16;
3342                         printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3343                         break;
3344                 }
3345
3346
3347
3348                 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3349                         xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3350                         xgi_video_info.refresh_rate);
3351
3352                 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3353                 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3354                 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3355
3356                 XGIfb_bpp_to_var(&default_var);
3357
3358                 default_var.pixclock = (u32) (1000000000 /
3359                                 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3360                                                 XGIfb_mode_no, XGIfb_rate_idx));
3361
3362                 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3363                          XGIfb_mode_no, XGIfb_rate_idx,
3364                          &default_var.left_margin, &default_var.right_margin,
3365                          &default_var.upper_margin, &default_var.lower_margin,
3366                          &default_var.hsync_len, &default_var.vsync_len,
3367                          &default_var.sync, &default_var.vmode)) {
3368
3369                    if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3370                       default_var.yres <<= 1;
3371                       default_var.yres_virtual <<= 1;
3372                    } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3373                       default_var.pixclock >>= 1;
3374                       default_var.yres >>= 1;
3375                       default_var.yres_virtual >>= 1;
3376                    }
3377
3378                 }
3379
3380                 xgi_video_info.accel = 0;
3381                 if(XGIfb_accel) {
3382                    xgi_video_info.accel = -1;
3383                    default_var.accel_flags |= FB_ACCELF_TEXT;
3384                    XGIfb_initaccel();
3385                 }
3386
3387                 fb_info->flags = FBINFO_FLAG_DEFAULT;
3388                 fb_info->var = default_var;
3389                 fb_info->fix = XGIfb_fix;
3390                 fb_info->par = &xgi_video_info;
3391                 fb_info->screen_base = xgi_video_info.video_vbase;
3392                 fb_info->fbops = &XGIfb_ops;
3393                 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3394                 fb_info->pseudo_palette = pseudo_palette;
3395
3396                 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3397
3398
3399 #ifdef CONFIG_MTRR
3400                 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3401                                 (unsigned int) xgi_video_info.video_size,
3402                                 MTRR_TYPE_WRCOMB, 1);
3403                 if(xgi_video_info.mtrr) {
3404                         printk(KERN_INFO "XGIfb: Added MTRRs\n");
3405                 }
3406 #endif
3407
3408                 if(register_framebuffer(fb_info) < 0)
3409     {
3410                         return -EINVAL;
3411     }
3412
3413                 XGIfb_registered = 1;
3414
3415                 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
3416                        XGIFB_GET_INFO);
3417
3418 /*              printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3419                      XGIfb_accel ? "enabled" : "disabled",
3420                      XGIfb_ypan  ? "ypan" : "redraw");
3421 */
3422                 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3423                         fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3424
3425
3426         }
3427
3428         dumpVGAReg();
3429
3430         return 0;
3431 }
3432
3433
3434 /*****************************************************/
3435 /*                PCI DEVICE HANDLING                */
3436 /*****************************************************/
3437
3438 static void __devexit xgifb_remove(struct pci_dev *pdev)
3439 {
3440         /* Unregister the framebuffer */
3441 //      if(xgi_video_info.registered) {
3442                 unregister_framebuffer(fb_info);
3443                 framebuffer_release(fb_info);
3444 //      }
3445
3446         pci_set_drvdata(pdev, NULL);
3447
3448 };
3449
3450 static struct pci_driver xgifb_driver = {
3451         .name           = "xgifb",
3452         .id_table       = xgifb_pci_table,
3453         .probe          = xgifb_probe,
3454         .remove         = __devexit_p(xgifb_remove)
3455 };
3456
3457 XGIINITSTATIC int __init xgifb_init(void)
3458 {
3459 #ifndef MODULE
3460         char *option = NULL;
3461
3462         if (fb_get_options("xgifb", &option))
3463                 return -ENODEV;
3464         XGIfb_setup(option);
3465 #endif
3466         return(pci_register_driver(&xgifb_driver));
3467 }
3468
3469
3470 #ifndef MODULE
3471 module_init(xgifb_init);
3472 #endif
3473
3474 /*****************************************************/
3475 /*                      MODULE                       */
3476 /*****************************************************/
3477
3478 #ifdef MODULE
3479
3480 static char         *mode = NULL;
3481 static int          vesa = 0;
3482 static unsigned int rate = 0;
3483 static unsigned int crt1off = 1;
3484 static unsigned int mem = 0;
3485 static char         *forcecrt2type = NULL;
3486 static int          forcecrt1 = -1;
3487 static int          pdc = -1;
3488 static int          pdc1 = -1;
3489 static int          noaccel = -1;
3490 static int          noypan  = -1;
3491 static int          nomax = -1;
3492 static int          userom = -1;
3493 static int          useoem = -1;
3494 static char         *tvstandard = NULL;
3495 static int          nocrt2rate = 0;
3496 static int          scalelcd = -1;
3497 static char         *specialtiming = NULL;
3498 static int          lvdshl = -1;
3499 static int          tvxposoffset = 0, tvyposoffset = 0;
3500 #if !defined(__i386__) && !defined(__x86_64__)
3501 static int          resetcard = 0;
3502 static int          videoram = 0;
3503 #endif
3504
3505 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3506 MODULE_LICENSE("GPL");
3507 MODULE_AUTHOR("XGITECH , Others");
3508
3509
3510
3511 module_param(mem, int, 0);
3512 module_param(noaccel, int, 0);
3513 module_param(noypan, int, 0);
3514 module_param(nomax, int, 0);
3515 module_param(userom, int, 0);
3516 module_param(useoem, int, 0);
3517 module_param(mode, charp, 0);
3518 module_param(vesa, int, 0);
3519 module_param(rate, int, 0);
3520 module_param(forcecrt1, int, 0);
3521 module_param(forcecrt2type, charp, 0);
3522 module_param(scalelcd, int, 0);
3523 module_param(pdc, int, 0);
3524 module_param(pdc1, int, 0);
3525 module_param(specialtiming, charp, 0);
3526 module_param(lvdshl, int, 0);
3527 module_param(tvstandard, charp, 0);
3528 module_param(tvxposoffset, int, 0);
3529 module_param(tvyposoffset, int, 0);
3530 module_param(filter, int, 0);
3531 module_param(nocrt2rate, int, 0);
3532 #if !defined(__i386__) && !defined(__x86_64__)
3533 module_param(resetcard, int, 0);
3534 module_param(videoram, int, 0);
3535 #endif
3536
3537
3538 MODULE_PARM_DESC(mem,
3539         "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3540           "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3541           "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3542           "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3543           "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3544           "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3545           "for XFree86 4.x/X.org 6.7 and later.\n");
3546
3547 MODULE_PARM_DESC(noaccel,
3548         "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3549           "(default: 0)\n");
3550
3551 MODULE_PARM_DESC(noypan,
3552         "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3553           "will be performed by redrawing the screen. (default: 0)\n");
3554
3555 MODULE_PARM_DESC(nomax,
3556         "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3557           "memory for the virtual screen in order to optimize scrolling performance. If\n"
3558           "this is set to anything other than 0, xgifb will not do this and thereby \n"
3559           "enable the user to positively specify a virtual Y size of the screen using\n"
3560           "fbset. (default: 0)\n");
3561
3562
3563
3564 MODULE_PARM_DESC(mode,
3565        "\nSelects the desired default display mode in the format XxYxDepth,\n"
3566          "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3567          "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3568          "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3569
3570 MODULE_PARM_DESC(vesa,
3571        "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3572          "0x117 (default: 0x0103)\n");
3573
3574
3575 MODULE_PARM_DESC(rate,
3576         "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3577           "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3578           "will be ignored (default: 60)\n");
3579
3580 MODULE_PARM_DESC(forcecrt1,
3581         "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3582           "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3583           "0=CRT1 OFF) (default: [autodetected])\n");
3584
3585 MODULE_PARM_DESC(forcecrt2type,
3586         "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3587           "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3588           "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3589           "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3590           "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3591           "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3592           "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3593           "depends on the very hardware in use. (default: [autodetected])\n");
3594
3595 MODULE_PARM_DESC(scalelcd,
3596         "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3597           "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3598           "show black bars around the image, TMDS panels will probably do the scaling\n"
3599           "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3600
3601 MODULE_PARM_DESC(pdc,
3602         "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3603           "should detect this correctly in most cases; however, sometimes this is not\n"
3604           "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3605           "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3606           "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3607           "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3608
3609 MODULE_PARM_DESC(pdc1,
3610         "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3611           "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3612           "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3613           "implemented yet.\n");
3614
3615 MODULE_PARM_DESC(specialtiming,
3616         "\nPlease refer to documentation for more information on this option.\n");
3617
3618 MODULE_PARM_DESC(lvdshl,
3619         "\nPlease refer to documentation for more information on this option.\n");
3620
3621 MODULE_PARM_DESC(tvstandard,
3622         "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3623           "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3624
3625 MODULE_PARM_DESC(tvxposoffset,
3626         "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3627           "Default: 0\n");
3628
3629 MODULE_PARM_DESC(tvyposoffset,
3630         "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3631           "Default: 0\n");
3632
3633 MODULE_PARM_DESC(filter,
3634         "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3635           "(Possible values 0-7, default: [no filter])\n");
3636
3637 MODULE_PARM_DESC(nocrt2rate,
3638         "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3639           "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3640
3641
3642
3643
3644 int __init xgifb_init_module(void)
3645 {
3646         printk("\nXGIfb_init_module");
3647         if(mode)
3648                 XGIfb_search_mode(mode);
3649         else if (vesa != -1)
3650                 XGIfb_search_vesamode(vesa);
3651
3652         return(xgifb_init());
3653 }
3654
3655 static void __exit xgifb_remove_module(void)
3656 {
3657         pci_unregister_driver(&xgifb_driver);
3658         printk(KERN_DEBUG "xgifb: Module unloaded\n");
3659 }
3660
3661 module_init(xgifb_init_module);
3662 module_exit(xgifb_remove_module);
3663
3664 #endif     /*  /MODULE  */
3665
3666 EXPORT_SYMBOL(XGI_malloc);
3667 EXPORT_SYMBOL(XGI_free);
3668