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