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