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