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