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