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