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