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