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