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