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