usb: dwc3: ep0: add handling for unaligned OUT transfers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / xgifb / XGI_main_26.c
blob4403e5f8059713d5062a8be65a574513c030c8f6
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/module.h>
9 #include <linux/moduleparam.h>
10 #include <linux/kernel.h>
11 #include <linux/spinlock.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/mm.h>
15 #include <linux/tty.h>
16 #include <linux/slab.h>
17 #include <linux/delay.h>
18 #include <linux/fb.h>
19 #include <linux/console.h>
20 #include <linux/selection.h>
21 #include <linux/ioport.h>
22 #include <linux/init.h>
23 #include <linux/pci.h>
24 #include <linux/vmalloc.h>
25 #include <linux/vt_kern.h>
26 #include <linux/capability.h>
27 #include <linux/fs.h>
28 #include <linux/types.h>
29 #include <linux/proc_fs.h>
31 #ifndef XGIFB_PAN
32 #define XGIFB_PAN
33 #endif
35 #include <linux/io.h>
36 #ifdef CONFIG_MTRR
37 #include <asm/mtrr.h>
38 #endif
40 #include "XGIfb.h"
41 #include "vgatypes.h"
42 #include "XGI_main.h"
43 #include "vb_init.h"
44 #include "vb_util.h"
45 #include "vb_setmode.h"
47 #define Index_CR_GPIO_Reg1 0x48
48 #define Index_CR_GPIO_Reg2 0x49
49 #define Index_CR_GPIO_Reg3 0x4a
51 #define GPIOG_EN (1<<6)
52 #define GPIOG_WRITE (1<<6)
53 #define GPIOG_READ (1<<1)
55 #define XGIFB_ROM_SIZE 65536
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 xgifb_reg_set(XGISR, 0x05, 0x86);
74 xgifb_reg_set(XGISR, 0x08, 0x4f);
75 xgifb_reg_set(XGISR, 0x0f, 0x20);
76 xgifb_reg_set(XGISR, 0x11, 0x4f);
77 xgifb_reg_set(XGISR, 0x13, 0x45);
78 xgifb_reg_set(XGISR, 0x14, 0x51);
79 xgifb_reg_set(XGISR, 0x1e, 0x41);
80 xgifb_reg_set(XGISR, 0x1f, 0x0);
81 xgifb_reg_set(XGISR, 0x20, 0xa1);
82 xgifb_reg_set(XGISR, 0x22, 0xfb);
83 xgifb_reg_set(XGISR, 0x26, 0x22);
84 xgifb_reg_set(XGISR, 0x3e, 0x07);
87 /* xgifb_reg_set(XGICR, 0x19, 0x00); */
88 /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
89 /* xgifb_reg_set(XGICR, 0x22, 0xff); */
90 /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
92 /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
94 /* xgifb_reg_set(XGICR, 0x57, 0x0); */
95 /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
97 /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
98 /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
100 xgifb_reg_set(XGICR, 0x99, 0x1);
101 xgifb_reg_set(XGICR, 0x41, 0x40);
104 for (i = 0; i < 0x4f; i++) {
105 reg = xgifb_reg_get(XGISR, i);
106 printk("\no 3c4 %x", i);
107 printk("\ni 3c5 => %x", reg);
110 for (i = 0; i < 0xF0; i++) {
111 reg = xgifb_reg_get(XGICR, i);
112 printk("\no 3d4 %x", i);
113 printk("\ni 3d5 => %x", reg);
116 xgifb_reg_set(XGIPART1,0x2F,1);
117 for (i=1; i < 0x50; i++) {
118 reg = xgifb_reg_get(XGIPART1, i);
119 printk("\no d004 %x", i);
120 printk("\ni d005 => %x", reg);
123 for (i=0; i < 0x50; i++) {
124 reg = xgifb_reg_get(XGIPART2, i);
125 printk("\no d010 %x", i);
126 printk("\ni d011 => %x", reg);
128 for (i=0; i < 0x50; i++) {
129 reg = xgifb_reg_get(XGIPART3, i);
130 printk("\no d012 %x",i);
131 printk("\ni d013 => %x",reg);
133 for (i=0; i < 0x50; i++) {
134 reg = xgifb_reg_get(XGIPART4, i);
135 printk("\no d014 %x",i);
136 printk("\ni d015 => %x",reg);
140 #else
141 static inline void dumpVGAReg(void)
144 #endif
146 /* data for XGI components */
147 struct video_info xgi_video_info;
149 #if 1
150 #define DEBUGPRN(x)
151 #else
152 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
153 #endif
155 /* --------------- Hardware Access Routines -------------------------- */
157 static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
158 struct xgi_hw_device_info *HwDeviceExtension,
159 unsigned char modeno, unsigned char rateindex)
161 unsigned short ModeNo = modeno;
162 unsigned short ModeIdIndex = 0, ClockIndex = 0;
163 unsigned short RefreshRateTableIndex = 0;
165 /* unsigned long temp = 0; */
166 int Clock;
167 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
168 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
170 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
171 ModeIdIndex, XGI_Pr);
174 temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
175 if (!temp) {
176 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
177 return 65000;
180 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
181 RefreshRateTableIndex += (rateindex - 1);
184 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
186 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
188 return Clock;
191 static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
192 struct xgi_hw_device_info *HwDeviceExtension,
193 unsigned char modeno, unsigned char rateindex,
194 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
195 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
196 u32 *vmode)
198 unsigned short ModeNo = modeno;
199 unsigned short ModeIdIndex = 0, index = 0;
200 unsigned short RefreshRateTableIndex = 0;
202 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
203 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
204 unsigned char sr_data, cr_data, cr_data2;
205 unsigned long cr_data3;
206 int A, B, C, D, E, F, temp, j;
207 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
208 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
209 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
210 ModeIdIndex, XGI_Pr);
212 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
213 if (!temp)
214 return 0;
216 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
217 RefreshRateTableIndex += (rateindex - 1);
219 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
221 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
223 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
225 /* Horizontal total */
226 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
227 A = HT + 5;
230 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
232 Horizontal display enable end
233 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
235 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
236 E = HDE + 1;
238 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
240 /* Horizontal retrace (=sync) start */
241 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
242 F = HRS - E - 3;
244 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
246 /* Horizontal blank start */
247 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
249 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
251 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
253 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
255 /* Horizontal blank end */
256 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
257 | ((unsigned short) (sr_data & 0x03) << 6);
259 /* Horizontal retrace (=sync) end */
260 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
262 temp = HBE - ((E - 1) & 255);
263 B = (temp > 0) ? temp : (temp + 256);
265 temp = HRE - ((E + F + 3) & 63);
266 C = (temp > 0) ? temp : (temp + 64);
268 D = B - F - C;
270 *left_margin = D * 8;
271 *right_margin = F * 8;
272 *hsync_len = C * 8;
274 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
276 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
278 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
280 /* Vertical total */
281 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
282 | ((unsigned short) (cr_data2 & 0x20) << 4)
283 | ((unsigned short) (sr_data & 0x01) << 10);
284 A = VT + 2;
286 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
288 /* Vertical display enable end */
290 VDE = (cr_data & 0xff) |
291 ((unsigned short) (cr_data2 & 0x02) << 7) |
292 ((unsigned short) (cr_data2 & 0x40) << 3) |
293 ((unsigned short) (sr_data & 0x02) << 9);
295 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
296 E = VDE + 1;
298 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
300 /* Vertical retrace (=sync) start */
301 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
302 | ((unsigned short) (cr_data2 & 0x80) << 2)
303 | ((unsigned short) (sr_data & 0x08) << 7);
304 F = VRS + 1 - E;
306 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
308 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
310 /* Vertical blank start */
311 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
312 | ((unsigned short) (cr_data3 & 0x20) << 4)
313 | ((unsigned short) (sr_data & 0x04) << 8);
315 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
317 /* Vertical blank end */
318 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
319 temp = VBE - ((E - 1) & 511);
320 B = (temp > 0) ? temp : (temp + 512);
322 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
324 /* Vertical retrace (=sync) end */
325 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
326 temp = VRE - ((E + F - 1) & 31);
327 C = (temp > 0) ? temp : (temp + 32);
329 D = B - F - C;
331 *upper_margin = D;
332 *lower_margin = F;
333 *vsync_len = C;
335 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
336 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
337 else
338 *sync |= FB_SYNC_VERT_HIGH_ACT;
340 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
341 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
342 else
343 *sync |= FB_SYNC_HOR_HIGH_ACT;
345 *vmode = FB_VMODE_NONINTERLACED;
346 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
347 *vmode = FB_VMODE_INTERLACED;
348 else {
349 j = 0;
350 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
351 if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
352 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
353 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
354 DoubleScanMode) {
355 *vmode = FB_VMODE_DOUBLE;
357 break;
359 j++;
363 return 1;
366 static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
368 XGI_Pr->RelIO = BaseAddr;
369 XGI_Pr->P3c4 = BaseAddr + 0x14;
370 XGI_Pr->P3d4 = BaseAddr + 0x24;
371 XGI_Pr->P3c0 = BaseAddr + 0x10;
372 XGI_Pr->P3ce = BaseAddr + 0x1e;
373 XGI_Pr->P3c2 = BaseAddr + 0x12;
374 XGI_Pr->P3ca = BaseAddr + 0x1a;
375 XGI_Pr->P3c6 = BaseAddr + 0x16;
376 XGI_Pr->P3c7 = BaseAddr + 0x17;
377 XGI_Pr->P3c8 = BaseAddr + 0x18;
378 XGI_Pr->P3c9 = BaseAddr + 0x19;
379 XGI_Pr->P3da = BaseAddr + 0x2A;
380 /* Digital video interface registers (LCD) */
381 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04;
382 /* 301 TV Encoder registers */
383 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10;
384 /* 301 Macrovision registers */
385 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12;
386 /* 301 VGA2 (and LCD) registers */
387 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14;
388 /* 301 palette address port registers */
389 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2;
393 /* ------------ Interface for init & mode switching code ------------- */
395 static unsigned char XGIfb_query_VGA_config_space(
396 struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset,
397 unsigned long set, unsigned long *value)
399 static struct pci_dev *pdev = NULL;
400 static unsigned char init = 0, valid_pdev = 0;
402 if (!set)
403 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
404 else
405 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
407 if (!init) {
408 init = 1;
409 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id,
410 pdev);
411 if (pdev) {
412 valid_pdev = 1;
413 pci_dev_put(pdev);
417 if (!valid_pdev) {
418 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
419 xgi_video_info.chip_id);
420 return 0;
423 if (set == 0)
424 pci_read_config_dword(pdev, offset, (u32 *) value);
425 else
426 pci_write_config_dword(pdev, offset, (u32)(*value));
428 return 1;
431 /* ------------------ Internal helper routines ----------------- */
433 static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
436 int found_mode = 0;
437 int XGIfb_mode_idx = 0;
439 found_mode = 0;
440 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
441 && (XGIbios_mode[XGIfb_mode_idx].xres
442 <= XGI21_LCDCapList[0].LVDSHDE)) {
443 if ((XGIbios_mode[XGIfb_mode_idx].xres
444 == XGI21_LCDCapList[0].LVDSHDE)
445 && (XGIbios_mode[XGIfb_mode_idx].yres
446 == XGI21_LCDCapList[0].LVDSVDE)
447 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
448 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
449 found_mode = 1;
450 break;
452 XGIfb_mode_idx++;
454 if (!found_mode)
455 XGIfb_mode_idx = 0;
457 return XGIfb_mode_idx;
460 static void XGIfb_search_mode(const char *name)
462 int i = 0, j = 0, l;
464 if (name == NULL) {
465 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
466 xgifb_mode_idx = DEFAULT_MODE;
467 if ((xgi_video_info.chip == XG21)
468 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
469 == DISPTYPE_LCD)) {
470 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
472 return;
475 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
476 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
477 xgifb_mode_idx = DEFAULT_MODE;
478 if ((xgi_video_info.chip == XG21)
479 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
480 == DISPTYPE_LCD)) {
481 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
483 return;
486 while (XGIbios_mode[i].mode_no != 0) {
487 l = min(strlen(name), strlen(XGIbios_mode[i].name));
488 if (!strncmp(name, XGIbios_mode[i].name, l)) {
489 xgifb_mode_idx = i;
490 j = 1;
491 break;
493 i++;
495 if (!j)
496 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
499 static void XGIfb_search_vesamode(unsigned int vesamode)
501 int i = 0, j = 0;
503 if (vesamode == 0) {
505 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
506 xgifb_mode_idx = DEFAULT_MODE;
507 if ((xgi_video_info.chip == XG21)
508 && ((xgi_video_info.disp_state & DISPTYPE_DISP2)
509 == DISPTYPE_LCD)) {
510 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
512 return;
515 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
517 while (XGIbios_mode[i].mode_no != 0) {
518 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
519 (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
520 xgifb_mode_idx = i;
521 j = 1;
522 break;
524 i++;
526 if (!j)
527 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
530 static int XGIfb_GetXG21LVDSData(void)
532 u8 tmp;
533 unsigned char *pData;
534 int i, j, k;
536 tmp = xgifb_reg_get(XGISR, 0x1e);
537 xgifb_reg_set(XGISR, 0x1e, tmp | 4);
539 pData = xgi_video_info.mmio_vbase + 0x20000;
540 if ((pData[0x0] == 0x55) &&
541 (pData[0x1] == 0xAA) &&
542 (pData[0x65] & 0x1)) {
543 i = pData[0x316] | (pData[0x317] << 8);
544 j = pData[i - 1];
545 if (j == 0xff)
546 j = 1;
548 k = 0;
549 do {
550 XGI21_LCDCapList[k].LVDS_Capability = pData[i]
551 | (pData[i + 1] << 8);
552 XGI21_LCDCapList[k].LVDSHT = pData[i + 2] | (pData[i
553 + 3] << 8);
554 XGI21_LCDCapList[k].LVDSVT = pData[i + 4] | (pData[i
555 + 5] << 8);
556 XGI21_LCDCapList[k].LVDSHDE = pData[i + 6] | (pData[i
557 + 7] << 8);
558 XGI21_LCDCapList[k].LVDSVDE = pData[i + 8] | (pData[i
559 + 9] << 8);
560 XGI21_LCDCapList[k].LVDSHFP = pData[i + 10] | (pData[i
561 + 11] << 8);
562 XGI21_LCDCapList[k].LVDSVFP = pData[i + 12] | (pData[i
563 + 13] << 8);
564 XGI21_LCDCapList[k].LVDSHSYNC = pData[i + 14]
565 | (pData[i + 15] << 8);
566 XGI21_LCDCapList[k].LVDSVSYNC = pData[i + 16]
567 | (pData[i + 17] << 8);
568 XGI21_LCDCapList[k].VCLKData1 = pData[i + 18];
569 XGI21_LCDCapList[k].VCLKData2 = pData[i + 19];
570 XGI21_LCDCapList[k].PSC_S1 = pData[i + 20];
571 XGI21_LCDCapList[k].PSC_S2 = pData[i + 21];
572 XGI21_LCDCapList[k].PSC_S3 = pData[i + 22];
573 XGI21_LCDCapList[k].PSC_S4 = pData[i + 23];
574 XGI21_LCDCapList[k].PSC_S5 = pData[i + 24];
575 i += 25;
576 j--;
577 k++;
578 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
579 / sizeof(struct XGI21_LVDSCapStruct))));
580 return 1;
582 return 0;
585 static int XGIfb_validate_mode(int myindex)
587 u16 xres, yres;
589 if (xgi_video_info.chip == XG21) {
590 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
591 == DISPTYPE_LCD) {
592 xres = XGI21_LCDCapList[0].LVDSHDE;
593 yres = XGI21_LCDCapList[0].LVDSVDE;
594 if (XGIbios_mode[myindex].xres > xres)
595 return -1;
596 if (XGIbios_mode[myindex].yres > yres)
597 return -1;
598 if ((XGIbios_mode[myindex].xres < xres) &&
599 (XGIbios_mode[myindex].yres < yres)) {
600 if (XGIbios_mode[myindex].bpp > 8)
601 return -1;
605 return myindex;
609 /* FIXME: for now, all is valid on XG27 */
610 if (xgi_video_info.chip == XG27)
611 return myindex;
613 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
614 return -1;
616 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
617 case DISPTYPE_LCD:
618 switch (XGIhw_ext.ulCRT2LCDType) {
619 case LCD_640x480:
620 xres = 640;
621 yres = 480;
622 break;
623 case LCD_800x600:
624 xres = 800;
625 yres = 600;
626 break;
627 case LCD_1024x600:
628 xres = 1024;
629 yres = 600;
630 break;
631 case LCD_1024x768:
632 xres = 1024;
633 yres = 768;
634 break;
635 case LCD_1152x768:
636 xres = 1152;
637 yres = 768;
638 break;
639 case LCD_1280x960:
640 xres = 1280;
641 yres = 960;
642 break;
643 case LCD_1280x768:
644 xres = 1280;
645 yres = 768;
646 break;
647 case LCD_1280x1024:
648 xres = 1280;
649 yres = 1024;
650 break;
651 case LCD_1400x1050:
652 xres = 1400;
653 yres = 1050;
654 break;
655 case LCD_1600x1200:
656 xres = 1600;
657 yres = 1200;
658 break;
659 /* case LCD_320x480: */ /* TW: FSTN */
661 xres = 320;
662 yres = 480;
663 break;
665 default:
666 xres = 0;
667 yres = 0;
668 break;
670 if (XGIbios_mode[myindex].xres > xres)
671 return -1;
672 if (XGIbios_mode[myindex].yres > yres)
673 return -1;
674 if ((XGIhw_ext.ulExternalChip == 0x01) || /* LVDS */
675 (XGIhw_ext.ulExternalChip == 0x05)) { /* LVDS+Chrontel */
676 switch (XGIbios_mode[myindex].xres) {
677 case 512:
678 if (XGIbios_mode[myindex].yres != 512)
679 return -1;
680 if (XGIhw_ext.ulCRT2LCDType == LCD_1024x600)
681 return -1;
682 break;
683 case 640:
684 if ((XGIbios_mode[myindex].yres != 400)
685 && (XGIbios_mode[myindex].yres
686 != 480))
687 return -1;
688 break;
689 case 800:
690 if (XGIbios_mode[myindex].yres != 600)
691 return -1;
692 break;
693 case 1024:
694 if ((XGIbios_mode[myindex].yres != 600) &&
695 (XGIbios_mode[myindex].yres != 768))
696 return -1;
697 if ((XGIbios_mode[myindex].yres == 600) &&
698 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
699 return -1;
700 break;
701 case 1152:
702 if ((XGIbios_mode[myindex].yres) != 768)
703 return -1;
704 if (XGIhw_ext.ulCRT2LCDType != LCD_1152x768)
705 return -1;
706 break;
707 case 1280:
708 if ((XGIbios_mode[myindex].yres != 768) &&
709 (XGIbios_mode[myindex].yres != 1024))
710 return -1;
711 if ((XGIbios_mode[myindex].yres == 768) &&
712 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
713 return -1;
714 break;
715 case 1400:
716 if (XGIbios_mode[myindex].yres != 1050)
717 return -1;
718 break;
719 case 1600:
720 if (XGIbios_mode[myindex].yres != 1200)
721 return -1;
722 break;
723 default:
724 return -1;
726 } else {
727 switch (XGIbios_mode[myindex].xres) {
728 case 512:
729 if (XGIbios_mode[myindex].yres != 512)
730 return -1;
731 break;
732 case 640:
733 if ((XGIbios_mode[myindex].yres != 400) &&
734 (XGIbios_mode[myindex].yres != 480))
735 return -1;
736 break;
737 case 800:
738 if (XGIbios_mode[myindex].yres != 600)
739 return -1;
740 break;
741 case 1024:
742 if (XGIbios_mode[myindex].yres != 768)
743 return -1;
744 break;
745 case 1280:
746 if ((XGIbios_mode[myindex].yres != 960) &&
747 (XGIbios_mode[myindex].yres != 1024))
748 return -1;
749 if (XGIbios_mode[myindex].yres == 960) {
750 if (XGIhw_ext.ulCRT2LCDType ==
751 LCD_1400x1050)
752 return -1;
754 break;
755 case 1400:
756 if (XGIbios_mode[myindex].yres != 1050)
757 return -1;
758 break;
759 case 1600:
760 if (XGIbios_mode[myindex].yres != 1200)
761 return -1;
762 break;
763 default:
764 return -1;
767 break;
768 case DISPTYPE_TV:
769 switch (XGIbios_mode[myindex].xres) {
770 case 512:
771 case 640:
772 case 800:
773 break;
774 case 720:
775 if (xgi_video_info.TV_type == TVMODE_NTSC) {
776 if (XGIbios_mode[myindex].yres != 480)
777 return -1;
778 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
779 if (XGIbios_mode[myindex].yres != 576)
780 return -1;
782 /* TW: LVDS/CHRONTEL does not support 720 */
783 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
784 xgi_video_info.hasVB == HASVB_CHRONTEL) {
785 return -1;
787 break;
788 case 1024:
789 if (xgi_video_info.TV_type == TVMODE_NTSC) {
790 if (XGIbios_mode[myindex].bpp == 32)
791 return -1;
793 break;
794 default:
795 return -1;
797 break;
798 case DISPTYPE_CRT2:
799 if (XGIbios_mode[myindex].xres > 1280)
800 return -1;
801 break;
803 return myindex;
807 static void XGIfb_search_crt2type(const char *name)
809 int i = 0;
811 if (name == NULL)
812 return;
814 while (XGI_crt2type[i].type_no != -1) {
815 if (!strcmp(name, XGI_crt2type[i].name)) {
816 XGIfb_crt2type = XGI_crt2type[i].type_no;
817 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
818 break;
820 i++;
822 if (XGIfb_crt2type < 0)
823 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
826 static u8 XGIfb_search_refresh_rate(unsigned int rate)
828 u16 xres, yres;
829 int i = 0;
831 xres = XGIbios_mode[xgifb_mode_idx].xres;
832 yres = XGIbios_mode[xgifb_mode_idx].yres;
834 XGIfb_rate_idx = 0;
835 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
836 if ((XGIfb_vrate[i].xres == xres) &&
837 (XGIfb_vrate[i].yres == yres)) {
838 if (XGIfb_vrate[i].refresh == rate) {
839 XGIfb_rate_idx = XGIfb_vrate[i].idx;
840 break;
841 } else if (XGIfb_vrate[i].refresh > rate) {
842 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
843 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
844 rate, XGIfb_vrate[i].refresh);
845 XGIfb_rate_idx = XGIfb_vrate[i].idx;
846 xgi_video_info.refresh_rate =
847 XGIfb_vrate[i].refresh;
848 } else if (((rate - XGIfb_vrate[i - 1].refresh)
849 <= 2) && (XGIfb_vrate[i].idx
850 != 1)) {
851 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
852 rate, XGIfb_vrate[i-1].refresh);
853 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
854 xgi_video_info.refresh_rate =
855 XGIfb_vrate[i - 1].refresh;
857 break;
858 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
859 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
860 rate, XGIfb_vrate[i].refresh);
861 XGIfb_rate_idx = XGIfb_vrate[i].idx;
862 break;
865 i++;
867 if (XGIfb_rate_idx > 0) {
868 return XGIfb_rate_idx;
869 } else {
870 printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n",
871 rate, xres, yres);
872 return 0;
876 static void XGIfb_search_tvstd(const char *name)
878 int i = 0;
880 if (name == NULL)
881 return;
883 while (XGI_tvtype[i].type_no != -1) {
884 if (!strcmp(name, XGI_tvtype[i].name)) {
885 XGIfb_tvmode = XGI_tvtype[i].type_no;
886 break;
888 i++;
892 /* ----------- FBDev related routines for all series ----------- */
894 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
896 switch (var->bits_per_pixel) {
897 case 8:
898 var->red.offset = var->green.offset = var->blue.offset = 0;
899 var->red.length = var->green.length = var->blue.length = 6;
900 xgi_video_info.video_cmap_len = 256;
901 break;
902 case 16:
903 var->red.offset = 11;
904 var->red.length = 5;
905 var->green.offset = 5;
906 var->green.length = 6;
907 var->blue.offset = 0;
908 var->blue.length = 5;
909 var->transp.offset = 0;
910 var->transp.length = 0;
911 xgi_video_info.video_cmap_len = 16;
912 break;
913 case 32:
914 var->red.offset = 16;
915 var->red.length = 8;
916 var->green.offset = 8;
917 var->green.length = 8;
918 var->blue.offset = 0;
919 var->blue.length = 8;
920 var->transp.offset = 24;
921 var->transp.length = 8;
922 xgi_video_info.video_cmap_len = 16;
923 break;
927 /* --------------------- SetMode routines ------------------------- */
929 static void XGIfb_pre_setmode(void)
931 u8 cr30 = 0, cr31 = 0;
933 cr31 = xgifb_reg_get(XGICR, 0x31);
934 cr31 &= ~0x60;
936 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
937 case DISPTYPE_CRT2:
938 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
939 cr31 |= XGI_DRIVER_MODE;
940 break;
941 case DISPTYPE_LCD:
942 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
943 cr31 |= XGI_DRIVER_MODE;
944 break;
945 case DISPTYPE_TV:
946 if (xgi_video_info.TV_type == TVMODE_HIVISION)
947 cr30 = (XGI_VB_OUTPUT_HIVISION
948 | XGI_SIMULTANEOUS_VIEW_ENABLE);
949 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
950 cr30 = (XGI_VB_OUTPUT_SVIDEO
951 | XGI_SIMULTANEOUS_VIEW_ENABLE);
952 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
953 cr30 = (XGI_VB_OUTPUT_COMPOSITE
954 | XGI_SIMULTANEOUS_VIEW_ENABLE);
955 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
956 cr30 = (XGI_VB_OUTPUT_SCART
957 | XGI_SIMULTANEOUS_VIEW_ENABLE);
958 cr31 |= XGI_DRIVER_MODE;
960 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
961 cr31 |= 0x01;
962 else
963 cr31 &= ~0x01;
964 break;
965 default: /* disable CRT2 */
966 cr30 = 0x00;
967 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
970 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
971 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
972 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
975 static void XGIfb_post_setmode(void)
977 u8 reg;
978 unsigned char doit = 1;
980 xgifb_reg_set(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
981 xgifb_reg_set(XGICR, 0x13, 0x00);
982 xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
983 *test*
985 if (xgi_video_info.video_bpp == 8) {
986 /* TW: We can't switch off CRT1 on LVDS/Chrontel
987 * in 8bpp Modes */
988 if ((xgi_video_info.hasVB == HASVB_LVDS) ||
989 (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
990 doit = 0;
992 /* TW: We can't switch off CRT1 on 301B-DH
993 * in 8bpp Modes if using LCD */
994 if (xgi_video_info.disp_state & DISPTYPE_LCD)
995 doit = 0;
998 /* TW: We can't switch off CRT1 if bridge is in slave mode */
999 if (xgi_video_info.hasVB != HASVB_NONE) {
1000 reg = xgifb_reg_get(XGIPART1, 0x00);
1002 if ((reg & 0x50) == 0x10)
1003 doit = 0;
1005 } else {
1006 XGIfb_crt1off = 0;
1009 reg = xgifb_reg_get(XGICR, 0x17);
1010 if ((XGIfb_crt1off) && (doit))
1011 reg &= ~0x80;
1012 else
1013 reg |= 0x80;
1014 xgifb_reg_set(XGICR, 0x17, reg);
1016 xgifb_reg_and(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
1018 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
1019 == HASVB_301)) {
1021 reg = xgifb_reg_get(XGIPART4, 0x01);
1023 if (reg < 0xB0) { /* Set filter for XGI301 */
1024 switch (xgi_video_info.video_width) {
1025 case 320:
1026 filter_tb = (xgi_video_info.TV_type ==
1027 TVMODE_NTSC) ? 4 : 12;
1028 break;
1029 case 640:
1030 filter_tb = (xgi_video_info.TV_type ==
1031 TVMODE_NTSC) ? 5 : 13;
1032 break;
1033 case 720:
1034 filter_tb = (xgi_video_info.TV_type ==
1035 TVMODE_NTSC) ? 6 : 14;
1036 break;
1037 case 800:
1038 filter_tb = (xgi_video_info.TV_type ==
1039 TVMODE_NTSC) ? 7 : 15;
1040 break;
1041 default:
1042 filter = -1;
1043 break;
1045 xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1047 if (xgi_video_info.TV_type == TVMODE_NTSC) {
1049 xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
1051 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
1053 xgifb_reg_and(XGIPART2, 0x30, 0xdf);
1055 } else if (xgi_video_info.TV_plug
1056 == TVPLUG_COMPOSITE) {
1058 xgifb_reg_or(XGIPART2, 0x30, 0x20);
1060 switch (xgi_video_info.video_width) {
1061 case 640:
1062 xgifb_reg_set(XGIPART2,
1063 0x35,
1064 0xEB);
1065 xgifb_reg_set(XGIPART2,
1066 0x36,
1067 0x04);
1068 xgifb_reg_set(XGIPART2,
1069 0x37,
1070 0x25);
1071 xgifb_reg_set(XGIPART2,
1072 0x38,
1073 0x18);
1074 break;
1075 case 720:
1076 xgifb_reg_set(XGIPART2,
1077 0x35,
1078 0xEE);
1079 xgifb_reg_set(XGIPART2,
1080 0x36,
1081 0x0C);
1082 xgifb_reg_set(XGIPART2,
1083 0x37,
1084 0x22);
1085 xgifb_reg_set(XGIPART2,
1086 0x38,
1087 0x08);
1088 break;
1089 case 800:
1090 xgifb_reg_set(XGIPART2,
1091 0x35,
1092 0xEB);
1093 xgifb_reg_set(XGIPART2,
1094 0x36,
1095 0x15);
1096 xgifb_reg_set(XGIPART2,
1097 0x37,
1098 0x25);
1099 xgifb_reg_set(XGIPART2,
1100 0x38,
1101 0xF6);
1102 break;
1106 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
1108 xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
1110 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
1112 xgifb_reg_and(XGIPART2, 0x30, 0xDF);
1114 } else if (xgi_video_info.TV_plug
1115 == TVPLUG_COMPOSITE) {
1117 xgifb_reg_or(XGIPART2, 0x30, 0x20);
1119 switch (xgi_video_info.video_width) {
1120 case 640:
1121 xgifb_reg_set(XGIPART2,
1122 0x35,
1123 0xF1);
1124 xgifb_reg_set(XGIPART2,
1125 0x36,
1126 0xF7);
1127 xgifb_reg_set(XGIPART2,
1128 0x37,
1129 0x1F);
1130 xgifb_reg_set(XGIPART2,
1131 0x38,
1132 0x32);
1133 break;
1134 case 720:
1135 xgifb_reg_set(XGIPART2,
1136 0x35,
1137 0xF3);
1138 xgifb_reg_set(XGIPART2,
1139 0x36,
1140 0x00);
1141 xgifb_reg_set(XGIPART2,
1142 0x37,
1143 0x1D);
1144 xgifb_reg_set(XGIPART2,
1145 0x38,
1146 0x20);
1147 break;
1148 case 800:
1149 xgifb_reg_set(XGIPART2,
1150 0x35,
1151 0xFC);
1152 xgifb_reg_set(XGIPART2,
1153 0x36,
1154 0xFB);
1155 xgifb_reg_set(XGIPART2,
1156 0x37,
1157 0x14);
1158 xgifb_reg_set(XGIPART2,
1159 0x38,
1160 0x2A);
1161 break;
1166 if ((filter >= 0) && (filter <= 7)) {
1167 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
1168 filter_tb, filter,
1169 XGI_TV_filter[filter_tb].
1170 filter[filter][0],
1171 XGI_TV_filter[filter_tb].
1172 filter[filter][1],
1173 XGI_TV_filter[filter_tb].
1174 filter[filter][2],
1175 XGI_TV_filter[filter_tb].
1176 filter[filter][3]
1178 xgifb_reg_set(
1179 XGIPART2,
1180 0x35,
1181 (XGI_TV_filter[filter_tb].
1182 filter[filter][0]));
1183 xgifb_reg_set(
1184 XGIPART2,
1185 0x36,
1186 (XGI_TV_filter[filter_tb].
1187 filter[filter][1]));
1188 xgifb_reg_set(
1189 XGIPART2,
1190 0x37,
1191 (XGI_TV_filter[filter_tb].
1192 filter[filter][2]));
1193 xgifb_reg_set(
1194 XGIPART2,
1195 0x38,
1196 (XGI_TV_filter[filter_tb].
1197 filter[filter][3]));
1203 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1204 struct fb_info *info)
1207 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1208 + var->hsync_len;
1209 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1210 + var->vsync_len;
1211 #if defined(__powerpc__)
1212 u8 sr_data, cr_data;
1213 #endif
1214 unsigned int drate = 0, hrate = 0;
1215 int found_mode = 0;
1216 int old_mode;
1217 /* unsigned char reg, reg1; */
1219 DEBUGPRN("Inside do_set_var");
1220 /* 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); */
1222 info->var.xres_virtual = var->xres_virtual;
1223 info->var.yres_virtual = var->yres_virtual;
1224 info->var.bits_per_pixel = var->bits_per_pixel;
1226 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1227 vtotal <<= 1;
1228 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1229 vtotal <<= 2;
1230 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1231 /* vtotal <<= 1; */
1232 /* var->yres <<= 1; */
1235 if (!htotal || !vtotal) {
1236 DPRINTK("XGIfb: Invalid 'var' information\n");
1237 return -EINVAL;
1238 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1239 var->pixclock, htotal, vtotal);
1241 if (var->pixclock && htotal && vtotal) {
1242 drate = 1000000000 / var->pixclock;
1243 hrate = (drate * 1000) / htotal;
1244 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1245 / vtotal);
1246 } else {
1247 xgi_video_info.refresh_rate = 60;
1250 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1251 var->xres,
1252 var->yres,
1253 var->bits_per_pixel,
1254 xgi_video_info.refresh_rate);
1256 old_mode = xgifb_mode_idx;
1257 xgifb_mode_idx = 0;
1259 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1260 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1261 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1262 && (XGIbios_mode[xgifb_mode_idx].yres
1263 == var->yres)
1264 && (XGIbios_mode[xgifb_mode_idx].bpp
1265 == var->bits_per_pixel)) {
1266 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1267 found_mode = 1;
1268 break;
1270 xgifb_mode_idx++;
1273 if (found_mode)
1274 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1275 else
1276 xgifb_mode_idx = -1;
1278 if (xgifb_mode_idx < 0) {
1279 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n",
1280 var->xres, var->yres, var->bits_per_pixel);
1281 xgifb_mode_idx = old_mode;
1282 return -EINVAL;
1285 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1286 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1287 xgi_video_info.refresh_rate = 60;
1290 if (isactive) {
1292 XGIfb_pre_setmode();
1293 if (XGISetModeNew(&XGIhw_ext, XGIfb_mode_no) == 0) {
1294 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
1295 XGIfb_mode_no);
1296 return -EINVAL;
1298 info->fix.line_length = ((info->var.xres_virtual
1299 * info->var.bits_per_pixel) >> 6);
1301 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1303 xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
1304 xgifb_reg_set(XGISR,
1305 0x0E,
1306 (info->fix.line_length & 0xff00) >> 8);
1308 XGIfb_post_setmode();
1310 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1311 XGIbios_mode[xgifb_mode_idx].xres,
1312 XGIbios_mode[xgifb_mode_idx].yres,
1313 XGIbios_mode[xgifb_mode_idx].bpp,
1314 xgi_video_info.refresh_rate);
1316 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1317 xgi_video_info.video_vwidth = info->var.xres_virtual;
1318 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1319 xgi_video_info.video_vheight = info->var.yres_virtual;
1320 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1321 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1322 xgi_video_info.video_linelength = info->var.xres_virtual
1323 * (xgi_video_info.video_bpp >> 3);
1324 switch (xgi_video_info.video_bpp) {
1325 case 8:
1326 xgi_video_info.DstColor = 0x0000;
1327 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1328 xgi_video_info.video_cmap_len = 256;
1329 #if defined(__powerpc__)
1330 cr_data = xgifb_reg_get(XGICR, 0x4D);
1331 xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
1332 #endif
1333 break;
1334 case 16:
1335 xgi_video_info.DstColor = 0x8000;
1336 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1337 #if defined(__powerpc__)
1338 cr_data = xgifb_reg_get(XGICR, 0x4D);
1339 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1340 #endif
1341 xgi_video_info.video_cmap_len = 16;
1342 break;
1343 case 32:
1344 xgi_video_info.DstColor = 0xC000;
1345 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1346 xgi_video_info.video_cmap_len = 16;
1347 #if defined(__powerpc__)
1348 cr_data = xgifb_reg_get(XGICR, 0x4D);
1349 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1350 #endif
1351 break;
1352 default:
1353 xgi_video_info.video_cmap_len = 16;
1354 printk(KERN_ERR "XGIfb: Unsupported depth %d",
1355 xgi_video_info.video_bpp);
1356 break;
1359 XGIfb_bpp_to_var(var); /*update ARGB info*/
1360 DEBUGPRN("End of do_set_var");
1362 dumpVGAReg();
1363 return 0;
1366 #ifdef XGIFB_PAN
1367 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1369 unsigned int base;
1371 /* printk("Inside pan_var"); */
1373 if (var->xoffset > (var->xres_virtual - var->xres)) {
1374 /* printk("Pan: xo: %d xv %d xr %d\n",
1375 var->xoffset, var->xres_virtual, var->xres); */
1376 return -EINVAL;
1378 if (var->yoffset > (var->yres_virtual - var->yres)) {
1379 /* printk("Pan: yo: %d yv %d yr %d\n",
1380 var->yoffset, var->yres_virtual, var->yres); */
1381 return -EINVAL;
1383 base = var->yoffset * var->xres_virtual + var->xoffset;
1385 /* calculate base bpp dep. */
1386 switch (var->bits_per_pixel) {
1387 case 16:
1388 base >>= 1;
1389 break;
1390 case 32:
1391 break;
1392 case 8:
1393 default:
1394 base >>= 2;
1395 break;
1398 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1400 xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1401 xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1402 xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1403 xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
1404 xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1406 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1407 xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1408 xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1409 xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1410 xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1411 xgifb_reg_and_or(XGIPART1,
1412 0x02,
1413 0x7F,
1414 ((base >> 24) & 0x01) << 7);
1416 /* printk("End of pan_var"); */
1417 return 0;
1419 #endif
1421 static int XGIfb_open(struct fb_info *info, int user)
1423 return 0;
1426 static int XGIfb_release(struct fb_info *info, int user)
1428 return 0;
1431 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1433 int rc = 16;
1435 switch (var->bits_per_pixel) {
1436 case 8:
1437 rc = 256;
1438 break;
1439 case 16:
1440 rc = 16;
1441 break;
1442 case 32:
1443 rc = 16;
1444 break;
1446 return rc;
1449 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1450 unsigned blue, unsigned transp, struct fb_info *info)
1452 if (regno >= XGIfb_get_cmap_len(&info->var))
1453 return 1;
1455 switch (info->var.bits_per_pixel) {
1456 case 8:
1457 outb(regno, XGIDACA);
1458 outb((red >> 10), XGIDACD);
1459 outb((green >> 10), XGIDACD);
1460 outb((blue >> 10), XGIDACD);
1461 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1462 outb(regno, XGIDAC2A);
1463 outb((red >> 8), XGIDAC2D);
1464 outb((green >> 8), XGIDAC2D);
1465 outb((blue >> 8), XGIDAC2D);
1467 break;
1468 case 16:
1469 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1470 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1471 >> 11);
1472 break;
1473 case 32:
1474 red >>= 8;
1475 green >>= 8;
1476 blue >>= 8;
1477 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1478 << 8) | (blue);
1479 break;
1481 return 0;
1484 /* ----------- FBDev related routines for all series ---------- */
1486 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1487 struct fb_info *info)
1489 DEBUGPRN("inside get_fix");
1490 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1492 strcpy(fix->id, myid);
1494 fix->smem_start = xgi_video_info.video_base;
1496 fix->smem_len = xgi_video_info.video_size;
1498 fix->type = video_type;
1499 fix->type_aux = 0;
1500 if (xgi_video_info.video_bpp == 8)
1501 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1502 else
1503 fix->visual = FB_VISUAL_DIRECTCOLOR;
1504 fix->xpanstep = 0;
1505 #ifdef XGIFB_PAN
1506 if (XGIfb_ypan)
1507 fix->ypanstep = 1;
1508 #endif
1509 fix->ywrapstep = 0;
1510 fix->line_length = xgi_video_info.video_linelength;
1511 fix->mmio_start = xgi_video_info.mmio_base;
1512 fix->mmio_len = xgi_video_info.mmio_size;
1513 fix->accel = FB_ACCEL_XGI_XABRE;
1515 DEBUGPRN("end of get_fix");
1516 return 0;
1519 static int XGIfb_set_par(struct fb_info *info)
1521 int err;
1523 /* printk("XGIfb: inside set_par\n"); */
1524 err = XGIfb_do_set_var(&info->var, 1, info);
1525 if (err)
1526 return err;
1527 XGIfb_get_fix(&info->fix, -1, info);
1528 /* printk("XGIfb: end of set_par\n"); */
1529 return 0;
1532 static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1534 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1535 + var->hsync_len;
1536 unsigned int vtotal = 0;
1537 unsigned int drate = 0, hrate = 0;
1538 int found_mode = 0;
1539 int refresh_rate, search_idx;
1541 DEBUGPRN("Inside check_var");
1543 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1544 vtotal = var->upper_margin + var->yres + var->lower_margin
1545 + var->vsync_len;
1546 vtotal <<= 1;
1547 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1548 vtotal = var->upper_margin + var->yres + var->lower_margin
1549 + var->vsync_len;
1550 vtotal <<= 2;
1551 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1552 vtotal = var->upper_margin + (var->yres / 2)
1553 + var->lower_margin + var->vsync_len;
1554 } else
1555 vtotal = var->upper_margin + var->yres + var->lower_margin
1556 + var->vsync_len;
1558 if (!(htotal) || !(vtotal))
1559 XGIFAIL("XGIfb: no valid timing data");
1561 if (var->pixclock && htotal && vtotal) {
1562 drate = 1000000000 / var->pixclock;
1563 hrate = (drate * 1000) / htotal;
1564 xgi_video_info.refresh_rate =
1565 (unsigned int) (hrate * 2 / vtotal);
1566 printk(KERN_DEBUG
1567 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1568 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1569 __func__, var->pixclock, htotal, vtotal,
1570 __func__, drate, hrate, xgi_video_info.refresh_rate);
1571 } else {
1572 xgi_video_info.refresh_rate = 60;
1576 if ((var->pixclock) && (htotal)) {
1577 drate = 1E12 / var->pixclock;
1578 hrate = drate / htotal;
1579 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1580 } else {
1581 refresh_rate = 60;
1584 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1585 if ((var->xres == 1024) && (var->yres == 600))
1586 refresh_rate = 60;
1588 search_idx = 0;
1589 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1590 (XGIbios_mode[search_idx].xres <= var->xres)) {
1591 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1592 (XGIbios_mode[search_idx].yres == var->yres) &&
1593 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1594 if (XGIfb_validate_mode(search_idx) > 0) {
1595 found_mode = 1;
1596 break;
1599 search_idx++;
1602 if (!found_mode) {
1604 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1605 var->xres, var->yres, var->bits_per_pixel);
1606 search_idx = 0;
1607 while (XGIbios_mode[search_idx].mode_no != 0) {
1608 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
1609 (var->yres <= XGIbios_mode[search_idx].yres) &&
1610 (var->bits_per_pixel ==
1611 XGIbios_mode[search_idx].bpp)) {
1612 if (XGIfb_validate_mode(search_idx) > 0) {
1613 found_mode = 1;
1614 break;
1617 search_idx++;
1619 if (found_mode) {
1620 var->xres = XGIbios_mode[search_idx].xres;
1621 var->yres = XGIbios_mode[search_idx].yres;
1622 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1623 var->xres, var->yres, var->bits_per_pixel);
1625 } else {
1626 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1627 var->xres, var->yres, var->bits_per_pixel);
1628 return -EINVAL;
1632 /* TW: TODO: Check the refresh rate */
1634 /* Adapt RGB settings */
1635 XGIfb_bpp_to_var(var);
1637 /* Sanity check for offsets */
1638 if (var->xoffset < 0)
1639 var->xoffset = 0;
1640 if (var->yoffset < 0)
1641 var->yoffset = 0;
1643 if (!XGIfb_ypan) {
1644 if (var->xres != var->xres_virtual)
1645 var->xres_virtual = var->xres;
1646 if (var->yres != var->yres_virtual)
1647 var->yres_virtual = var->yres;
1648 } /* else { */
1649 /* TW: Now patch yres_virtual if we use panning */
1650 /* May I do this? */
1651 /* var->yres_virtual = xgi_video_info.heapstart /
1652 (var->xres * (var->bits_per_pixel >> 3)); */
1653 /* if (var->yres_virtual <= var->yres) { */
1654 /* TW: Paranoia check */
1655 /* var->yres_virtual = var->yres; */
1656 /* } */
1657 /* } */
1659 /* Truncate offsets to maximum if too high */
1660 if (var->xoffset > var->xres_virtual - var->xres)
1661 var->xoffset = var->xres_virtual - var->xres - 1;
1663 if (var->yoffset > var->yres_virtual - var->yres)
1664 var->yoffset = var->yres_virtual - var->yres - 1;
1666 /* Set everything else to 0 */
1667 var->red.msb_right =
1668 var->green.msb_right =
1669 var->blue.msb_right =
1670 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1672 DEBUGPRN("end of check_var");
1673 return 0;
1676 #ifdef XGIFB_PAN
1677 static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1678 struct fb_info *info)
1680 int err;
1682 /* printk("\nInside pan_display:\n"); */
1684 if (var->xoffset > (var->xres_virtual - var->xres))
1685 return -EINVAL;
1686 if (var->yoffset > (var->yres_virtual - var->yres))
1687 return -EINVAL;
1689 if (var->vmode & FB_VMODE_YWRAP) {
1690 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1691 || var->xoffset)
1692 return -EINVAL;
1693 } else {
1694 if (var->xoffset + info->var.xres > info->var.xres_virtual
1695 || var->yoffset + info->var.yres
1696 > info->var.yres_virtual)
1697 return -EINVAL;
1699 err = XGIfb_pan_var(var);
1700 if (err < 0)
1701 return err;
1703 info->var.xoffset = var->xoffset;
1704 info->var.yoffset = var->yoffset;
1705 if (var->vmode & FB_VMODE_YWRAP)
1706 info->var.vmode |= FB_VMODE_YWRAP;
1707 else
1708 info->var.vmode &= ~FB_VMODE_YWRAP;
1710 /* printk("End of pan_display\n"); */
1711 return 0;
1713 #endif
1715 static int XGIfb_blank(int blank, struct fb_info *info)
1717 u8 reg;
1719 reg = xgifb_reg_get(XGICR, 0x17);
1721 if (blank > 0)
1722 reg &= 0x7f;
1723 else
1724 reg |= 0x80;
1726 xgifb_reg_set(XGICR, 0x17, reg);
1727 xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1728 xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
1729 return 0;
1732 static struct fb_ops XGIfb_ops = {
1733 .owner = THIS_MODULE,
1734 .fb_open = XGIfb_open,
1735 .fb_release = XGIfb_release,
1736 .fb_check_var = XGIfb_check_var,
1737 .fb_set_par = XGIfb_set_par,
1738 .fb_setcolreg = XGIfb_setcolreg,
1739 #ifdef XGIFB_PAN
1740 .fb_pan_display = XGIfb_pan_display,
1741 #endif
1742 .fb_blank = XGIfb_blank,
1743 .fb_fillrect = cfb_fillrect,
1744 .fb_copyarea = cfb_copyarea,
1745 .fb_imageblit = cfb_imageblit,
1746 /* .fb_mmap = XGIfb_mmap, */
1749 /* ---------------- Chip generation dependent routines ---------------- */
1751 /* for XGI 315/550/650/740/330 */
1753 static int XGIfb_get_dram_size(void)
1756 u8 ChannelNum, tmp;
1757 u8 reg = 0;
1759 /* xorg driver sets 32MB * 1 channel */
1760 if (xgi_video_info.chip == XG27)
1761 xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1763 reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE);
1764 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1765 case XGI_DRAM_SIZE_1MB:
1766 xgi_video_info.video_size = 0x100000;
1767 break;
1768 case XGI_DRAM_SIZE_2MB:
1769 xgi_video_info.video_size = 0x200000;
1770 break;
1771 case XGI_DRAM_SIZE_4MB:
1772 xgi_video_info.video_size = 0x400000;
1773 break;
1774 case XGI_DRAM_SIZE_8MB:
1775 xgi_video_info.video_size = 0x800000;
1776 break;
1777 case XGI_DRAM_SIZE_16MB:
1778 xgi_video_info.video_size = 0x1000000;
1779 break;
1780 case XGI_DRAM_SIZE_32MB:
1781 xgi_video_info.video_size = 0x2000000;
1782 break;
1783 case XGI_DRAM_SIZE_64MB:
1784 xgi_video_info.video_size = 0x4000000;
1785 break;
1786 case XGI_DRAM_SIZE_128MB:
1787 xgi_video_info.video_size = 0x8000000;
1788 break;
1789 case XGI_DRAM_SIZE_256MB:
1790 xgi_video_info.video_size = 0x10000000;
1791 break;
1792 default:
1793 return -1;
1796 tmp = (reg & 0x0c) >> 2;
1797 switch (xgi_video_info.chip) {
1798 case XG20:
1799 case XG21:
1800 case XG27:
1801 ChannelNum = 1;
1802 break;
1804 case XG42:
1805 if (reg & 0x04)
1806 ChannelNum = 2;
1807 else
1808 ChannelNum = 1;
1809 break;
1811 case XG45:
1812 if (tmp == 1)
1813 ChannelNum = 2;
1814 else if (tmp == 2)
1815 ChannelNum = 3;
1816 else if (tmp == 3)
1817 ChannelNum = 4;
1818 else
1819 ChannelNum = 1;
1820 break;
1822 case XG40:
1823 default:
1824 if (tmp == 2)
1825 ChannelNum = 2;
1826 else if (tmp == 3)
1827 ChannelNum = 3;
1828 else
1829 ChannelNum = 1;
1830 break;
1833 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1834 /* PLiad fixed for benchmarking and fb set */
1835 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1836 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
1838 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
1839 reg,
1840 xgi_video_info.video_size, ChannelNum);
1841 return 0;
1845 static void XGIfb_detect_VB(void)
1847 u8 cr32, temp = 0;
1849 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1851 switch (xgi_video_info.hasVB) {
1852 case HASVB_LVDS_CHRONTEL:
1853 case HASVB_CHRONTEL:
1854 break;
1855 case HASVB_301:
1856 case HASVB_302:
1857 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1858 break;
1861 cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
1863 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1864 XGIfb_crt1off = 0;
1865 else {
1866 if (cr32 & 0x5F)
1867 XGIfb_crt1off = 1;
1868 else
1869 XGIfb_crt1off = 0;
1872 if (XGIfb_crt2type != -1)
1873 /* TW: Override with option */
1874 xgi_video_info.disp_state = XGIfb_crt2type;
1875 else if (cr32 & XGI_VB_TV)
1876 xgi_video_info.disp_state = DISPTYPE_TV;
1877 else if (cr32 & XGI_VB_LCD)
1878 xgi_video_info.disp_state = DISPTYPE_LCD;
1879 else if (cr32 & XGI_VB_CRT2)
1880 xgi_video_info.disp_state = DISPTYPE_CRT2;
1881 else
1882 xgi_video_info.disp_state = 0;
1884 if (XGIfb_tvplug != -1)
1885 /* PR/TW: Override with option */
1886 xgi_video_info.TV_plug = XGIfb_tvplug;
1887 else if (cr32 & XGI_VB_HIVISION) {
1888 xgi_video_info.TV_type = TVMODE_HIVISION;
1889 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1890 } else if (cr32 & XGI_VB_SVIDEO)
1891 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1892 else if (cr32 & XGI_VB_COMPOSITE)
1893 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1894 else if (cr32 & XGI_VB_SCART)
1895 xgi_video_info.TV_plug = TVPLUG_SCART;
1897 if (xgi_video_info.TV_type == 0) {
1898 temp = xgifb_reg_get(XGICR, 0x38);
1899 if (temp & 0x10)
1900 xgi_video_info.TV_type = TVMODE_PAL;
1901 else
1902 xgi_video_info.TV_type = TVMODE_NTSC;
1905 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1906 if (XGIfb_forcecrt1 != -1) {
1907 if (XGIfb_forcecrt1)
1908 XGIfb_crt1off = 0;
1909 else
1910 XGIfb_crt1off = 1;
1914 static int XGIfb_has_VB(void)
1916 u8 vb_chipid;
1918 vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
1919 switch (vb_chipid) {
1920 case 0x01:
1921 xgi_video_info.hasVB = HASVB_301;
1922 break;
1923 case 0x02:
1924 xgi_video_info.hasVB = HASVB_302;
1925 break;
1926 default:
1927 xgi_video_info.hasVB = HASVB_NONE;
1928 return 0;
1930 return 1;
1933 static void XGIfb_get_VB_type(void)
1935 u8 reg;
1937 if (!XGIfb_has_VB()) {
1938 reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
1939 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1940 case XGI310_EXTERNAL_CHIP_LVDS:
1941 xgi_video_info.hasVB = HASVB_LVDS;
1942 break;
1943 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1944 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1945 break;
1946 default:
1947 break;
1952 XGIINITSTATIC int __init XGIfb_setup(char *options)
1954 char *this_opt;
1956 xgi_video_info.refresh_rate = 0;
1958 printk(KERN_INFO "XGIfb: Options %s\n", options);
1960 if (!options || !*options)
1961 return 0;
1963 while ((this_opt = strsep(&options, ",")) != NULL) {
1965 if (!*this_opt)
1966 continue;
1968 if (!strncmp(this_opt, "mode:", 5)) {
1969 XGIfb_search_mode(this_opt + 5);
1970 } else if (!strncmp(this_opt, "vesa:", 5)) {
1971 XGIfb_search_vesamode(simple_strtoul(
1972 this_opt + 5, NULL, 0));
1973 } else if (!strncmp(this_opt, "mode:", 5)) {
1974 XGIfb_search_mode(this_opt + 5);
1975 } else if (!strncmp(this_opt, "vesa:", 5)) {
1976 XGIfb_search_vesamode(simple_strtoul(
1977 this_opt + 5, NULL, 0));
1978 } else if (!strncmp(this_opt, "vrate:", 6)) {
1979 xgi_video_info.refresh_rate = simple_strtoul(
1980 this_opt + 6, NULL, 0);
1981 } else if (!strncmp(this_opt, "rate:", 5)) {
1982 xgi_video_info.refresh_rate = simple_strtoul(
1983 this_opt + 5, NULL, 0);
1984 } else if (!strncmp(this_opt, "off", 3)) {
1985 XGIfb_off = 1;
1986 } else if (!strncmp(this_opt, "crt1off", 7)) {
1987 XGIfb_crt1off = 1;
1988 } else if (!strncmp(this_opt, "filter:", 7)) {
1989 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
1990 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
1991 XGIfb_search_crt2type(this_opt + 14);
1992 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
1993 XGIfb_forcecrt1 = (int)simple_strtoul(
1994 this_opt + 10, NULL, 0);
1995 } else if (!strncmp(this_opt, "tvmode:", 7)) {
1996 XGIfb_search_tvstd(this_opt + 7);
1997 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
1998 XGIfb_search_tvstd(this_opt + 7);
1999 } else if (!strncmp(this_opt, "dstn", 4)) {
2000 enable_dstn = 1;
2001 /* TW: DSTN overrules forcecrt2type */
2002 XGIfb_crt2type = DISPTYPE_LCD;
2003 } else if (!strncmp(this_opt, "pdc:", 4)) {
2004 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2005 if (XGIfb_pdc & ~0x3c) {
2006 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2007 XGIfb_pdc = 0;
2009 } else if (!strncmp(this_opt, "noypan", 6)) {
2010 XGIfb_ypan = 0;
2011 } else if (!strncmp(this_opt, "userom:", 7)) {
2012 XGIfb_userom = (int)simple_strtoul(
2013 this_opt + 7, NULL, 0);
2014 /* } else if (!strncmp(this_opt, "useoem:", 7)) { */
2015 /* XGIfb_useoem = (int)simple_strtoul(
2016 this_opt + 7, NULL, 0); */
2017 } else {
2018 XGIfb_search_mode(this_opt);
2019 /* printk(KERN_INFO "XGIfb: Invalid option %s\n",
2020 this_opt); */
2023 /* TW: Panning only with acceleration */
2024 XGIfb_ypan = 0;
2027 printk("\nxgifb: outa xgifb_setup 3450");
2028 return 0;
2031 static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
2033 void __iomem *rom_address;
2034 unsigned char *rom_copy;
2035 size_t rom_size;
2037 rom_address = pci_map_rom(dev, &rom_size);
2038 if (rom_address == NULL)
2039 return NULL;
2041 rom_copy = vzalloc(XGIFB_ROM_SIZE);
2042 if (rom_copy == NULL)
2043 goto done;
2045 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
2046 memcpy_fromio(rom_copy, rom_address, rom_size);
2048 done:
2049 pci_unmap_rom(dev, rom_address);
2050 return rom_copy;
2053 static int __devinit xgifb_probe(struct pci_dev *pdev,
2054 const struct pci_device_id *ent)
2056 u8 reg, reg1;
2057 u8 CR48, CR38;
2058 int ret;
2060 if (XGIfb_off)
2061 return -ENXIO;
2063 XGIfb_registered = 0;
2065 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
2066 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2067 if (!fb_info)
2068 return -ENOMEM;
2070 xgi_video_info.chip_id = pdev->device;
2071 pci_read_config_byte(pdev,
2072 PCI_REVISION_ID,
2073 &xgi_video_info.revision_id);
2074 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2076 xgi_video_info.pcibus = pdev->bus->number;
2077 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2078 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2079 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2080 xgi_video_info.subsysdevice = pdev->subsystem_device;
2082 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2083 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2084 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
2085 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2086 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2087 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2088 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2089 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2091 if (pci_enable_device(pdev)) {
2092 ret = -EIO;
2093 goto error;
2096 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
2098 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2099 reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD);
2101 if (reg1 != 0xa1) { /*I/O error */
2102 printk("\nXGIfb: I/O error!!!");
2103 ret = -EIO;
2104 goto error;
2107 switch (xgi_video_info.chip_id) {
2108 case PCI_DEVICE_ID_XG_20:
2109 xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2110 CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
2111 if (CR48&GPIOG_READ)
2112 xgi_video_info.chip = XG21;
2113 else
2114 xgi_video_info.chip = XG20;
2115 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2116 break;
2117 case PCI_DEVICE_ID_XG_40:
2118 xgi_video_info.chip = XG40;
2119 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2120 break;
2121 case PCI_DEVICE_ID_XG_41:
2122 xgi_video_info.chip = XG41;
2123 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2124 break;
2125 case PCI_DEVICE_ID_XG_42:
2126 xgi_video_info.chip = XG42;
2127 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2128 break;
2129 case PCI_DEVICE_ID_XG_27:
2130 xgi_video_info.chip = XG27;
2131 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2132 break;
2133 default:
2134 ret = -ENODEV;
2135 goto error;
2138 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
2139 XGIhw_ext.jChipType = xgi_video_info.chip;
2141 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
2142 XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
2143 if (XGIhw_ext.pjVirtualRomBase)
2144 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",
2145 XGIhw_ext.pjVirtualRomBase);
2146 else
2147 printk(KERN_INFO "XGIfb: Video ROM not found\n");
2148 } else {
2149 XGIhw_ext.pjVirtualRomBase = NULL;
2150 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2152 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2154 if (XGIfb_get_dram_size()) {
2155 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
2156 ret = -ENODEV;
2157 goto error;
2160 if ((xgifb_mode_idx < 0) ||
2161 ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2162 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
2163 xgifb_reg_or(XGISR,
2164 IND_XGI_PCI_ADDRESS_SET,
2165 (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
2166 /* Enable 2D accelerator engine */
2167 xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
2170 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
2172 if (!request_mem_region(xgi_video_info.video_base,
2173 xgi_video_info.video_size,
2174 "XGIfb FB")) {
2175 printk("unable request memory size %x",
2176 xgi_video_info.video_size);
2177 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
2178 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
2179 ret = -ENODEV;
2180 goto error;
2183 if (!request_mem_region(xgi_video_info.mmio_base,
2184 xgi_video_info.mmio_size,
2185 "XGIfb MMIO")) {
2186 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
2187 ret = -ENODEV;
2188 goto error_0;
2191 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
2192 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
2193 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
2194 xgi_video_info.mmio_size);
2196 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
2197 xgi_video_info.video_base,
2198 xgi_video_info.video_vbase,
2199 xgi_video_info.video_size / 1024);
2201 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
2202 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
2203 xgi_video_info.mmio_size / 1024);
2204 printk("XGIfb: XGIInitNew() ...");
2205 if (XGIInitNew(&XGIhw_ext))
2206 printk("OK\n");
2207 else
2208 printk("Fail\n");
2210 xgi_video_info.mtrr = (unsigned int) 0;
2212 if ((xgifb_mode_idx < 0) ||
2213 ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
2214 xgi_video_info.hasVB = HASVB_NONE;
2215 if ((xgi_video_info.chip == XG20) ||
2216 (xgi_video_info.chip == XG27)) {
2217 xgi_video_info.hasVB = HASVB_NONE;
2218 } else if (xgi_video_info.chip == XG21) {
2219 CR38 = xgifb_reg_get(XGICR, 0x38);
2220 if ((CR38&0xE0) == 0xC0) {
2221 xgi_video_info.disp_state = DISPTYPE_LCD;
2222 if (!XGIfb_GetXG21LVDSData()) {
2223 int m;
2224 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
2225 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
2226 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
2227 xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
2231 } else if ((CR38&0xE0) == 0x60) {
2232 xgi_video_info.hasVB = HASVB_CHRONTEL;
2233 } else {
2234 xgi_video_info.hasVB = HASVB_NONE;
2236 } else {
2237 XGIfb_get_VB_type();
2240 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
2242 XGIhw_ext.ulExternalChip = 0;
2244 switch (xgi_video_info.hasVB) {
2245 case HASVB_301:
2246 reg = xgifb_reg_get(XGIPART4, 0x01);
2247 if (reg >= 0xE0) {
2248 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2249 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2250 } else if (reg >= 0xD0) {
2251 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2252 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
2254 /* else if (reg >= 0xB0) {
2255 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
2256 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2257 printk("XGIfb: XGI301B bridge detected\n");
2258 } */
2259 else {
2260 XGIhw_ext.ujVBChipID = VB_CHIP_301;
2261 printk("XGIfb: XGI301 bridge detected\n");
2263 break;
2264 case HASVB_302:
2265 reg = xgifb_reg_get(XGIPART4, 0x01);
2266 if (reg >= 0xE0) {
2267 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
2268 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2269 } else if (reg >= 0xD0) {
2270 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
2271 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2272 } else if (reg >= 0xB0) {
2273 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2275 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
2277 } else {
2278 XGIhw_ext.ujVBChipID = VB_CHIP_302;
2279 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
2281 break;
2282 case HASVB_LVDS:
2283 XGIhw_ext.ulExternalChip = 0x1;
2284 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
2285 break;
2286 case HASVB_TRUMPION:
2287 XGIhw_ext.ulExternalChip = 0x2;
2288 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
2289 break;
2290 case HASVB_CHRONTEL:
2291 XGIhw_ext.ulExternalChip = 0x4;
2292 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
2293 break;
2294 case HASVB_LVDS_CHRONTEL:
2295 XGIhw_ext.ulExternalChip = 0x5;
2296 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2297 break;
2298 default:
2299 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
2300 break;
2303 if (xgi_video_info.hasVB != HASVB_NONE)
2304 XGIfb_detect_VB();
2306 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2307 if (XGIfb_crt1off)
2308 xgi_video_info.disp_state |= DISPMODE_SINGLE;
2309 else
2310 xgi_video_info.disp_state |= (DISPMODE_MIRROR |
2311 DISPTYPE_CRT1);
2312 } else {
2313 xgi_video_info.disp_state = DISPMODE_SINGLE |
2314 DISPTYPE_CRT1;
2317 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2318 if (!enable_dstn) {
2319 reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2320 reg &= 0x0f;
2321 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
2323 } else {
2324 /* TW: FSTN/DSTN */
2325 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
2329 XGIfb_detectedpdc = 0;
2331 XGIfb_detectedlcda = 0xff;
2333 /* TW: Try to find about LCDA */
2335 if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
2336 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2337 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) {
2338 int tmp;
2339 tmp = xgifb_reg_get(XGICR, 0x34);
2340 if (tmp <= 0x13) {
2341 /* Currently on LCDA?
2342 *(Some BIOSes leave CR38) */
2343 tmp = xgifb_reg_get(XGICR, 0x38);
2344 if ((tmp & 0x03) == 0x03) {
2345 /* XGI_Pr.XGI_UseLCDA = 1; */
2346 } else {
2347 /* Currently on LCDA?
2348 *(Some newer BIOSes set D0 in CR35) */
2349 tmp = xgifb_reg_get(XGICR, 0x35);
2350 if (tmp & 0x01) {
2351 /* XGI_Pr.XGI_UseLCDA = 1; */
2352 } else {
2353 tmp = xgifb_reg_get(XGICR,
2354 0x30);
2355 if (tmp & 0x20) {
2356 tmp = xgifb_reg_get(
2357 XGIPART1, 0x13);
2358 if (tmp & 0x04) {
2359 /* XGI_Pr.XGI_UseLCDA = 1; */
2368 if (xgifb_mode_idx >= 0)
2369 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
2371 if (xgifb_mode_idx < 0) {
2372 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2373 case DISPTYPE_LCD:
2374 xgifb_mode_idx = DEFAULT_LCDMODE;
2375 if (xgi_video_info.chip == XG21)
2376 xgifb_mode_idx =
2377 XGIfb_GetXG21DefaultLVDSModeIdx();
2378 break;
2379 case DISPTYPE_TV:
2380 xgifb_mode_idx = DEFAULT_TVMODE;
2381 break;
2382 default:
2383 xgifb_mode_idx = DEFAULT_MODE;
2384 break;
2388 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
2390 /* yilin set default refresh rate */
2391 if (xgi_video_info.refresh_rate == 0)
2392 xgi_video_info.refresh_rate = 60;
2393 if (XGIfb_search_refresh_rate(
2394 xgi_video_info.refresh_rate) == 0) {
2395 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
2396 xgi_video_info.refresh_rate = 60;
2399 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
2400 xgi_video_info.video_vwidth =
2401 xgi_video_info.video_width =
2402 XGIbios_mode[xgifb_mode_idx].xres;
2403 xgi_video_info.video_vheight =
2404 xgi_video_info.video_height =
2405 XGIbios_mode[xgifb_mode_idx].yres;
2406 xgi_video_info.org_x = xgi_video_info.org_y = 0;
2407 xgi_video_info.video_linelength =
2408 xgi_video_info.video_width *
2409 (xgi_video_info.video_bpp >> 3);
2410 switch (xgi_video_info.video_bpp) {
2411 case 8:
2412 xgi_video_info.DstColor = 0x0000;
2413 xgi_video_info.XGI310_AccelDepth = 0x00000000;
2414 xgi_video_info.video_cmap_len = 256;
2415 break;
2416 case 16:
2417 xgi_video_info.DstColor = 0x8000;
2418 xgi_video_info.XGI310_AccelDepth = 0x00010000;
2419 xgi_video_info.video_cmap_len = 16;
2420 break;
2421 case 32:
2422 xgi_video_info.DstColor = 0xC000;
2423 xgi_video_info.XGI310_AccelDepth = 0x00020000;
2424 xgi_video_info.video_cmap_len = 16;
2425 break;
2426 default:
2427 xgi_video_info.video_cmap_len = 16;
2428 printk(KERN_INFO "XGIfb: Unsupported depth %d",
2429 xgi_video_info.video_bpp);
2430 break;
2433 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
2434 xgi_video_info.video_width,
2435 xgi_video_info.video_height,
2436 xgi_video_info.video_bpp,
2437 xgi_video_info.refresh_rate);
2439 default_var.xres =
2440 default_var.xres_virtual =
2441 xgi_video_info.video_width;
2442 default_var.yres =
2443 default_var.yres_virtual =
2444 xgi_video_info.video_height;
2445 default_var.bits_per_pixel = xgi_video_info.video_bpp;
2447 XGIfb_bpp_to_var(&default_var);
2449 default_var.pixclock = (u32) (1000000000 /
2450 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
2451 XGIfb_mode_no, XGIfb_rate_idx));
2453 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
2454 XGIfb_mode_no, XGIfb_rate_idx,
2455 &default_var.left_margin, &default_var.right_margin,
2456 &default_var.upper_margin, &default_var.lower_margin,
2457 &default_var.hsync_len, &default_var.vsync_len,
2458 &default_var.sync, &default_var.vmode)) {
2460 if ((default_var.vmode & FB_VMODE_MASK) ==
2461 FB_VMODE_INTERLACED) {
2462 default_var.yres <<= 1;
2463 default_var.yres_virtual <<= 1;
2464 } else if ((default_var.vmode & FB_VMODE_MASK) ==
2465 FB_VMODE_DOUBLE) {
2466 default_var.pixclock >>= 1;
2467 default_var.yres >>= 1;
2468 default_var.yres_virtual >>= 1;
2473 fb_info->flags = FBINFO_FLAG_DEFAULT;
2474 fb_info->var = default_var;
2475 fb_info->fix = XGIfb_fix;
2476 fb_info->par = &xgi_video_info;
2477 fb_info->screen_base = xgi_video_info.video_vbase;
2478 fb_info->fbops = &XGIfb_ops;
2479 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
2480 fb_info->pseudo_palette = pseudo_palette;
2482 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2484 #ifdef CONFIG_MTRR
2485 xgi_video_info.mtrr = mtrr_add(
2486 (unsigned int) xgi_video_info.video_base,
2487 (unsigned int) xgi_video_info.video_size,
2488 MTRR_TYPE_WRCOMB, 1);
2489 if (xgi_video_info.mtrr)
2490 printk(KERN_INFO "XGIfb: Added MTRRs\n");
2491 #endif
2493 if (register_framebuffer(fb_info) < 0) {
2494 ret = -EINVAL;
2495 goto error_1;
2498 XGIfb_registered = 1;
2500 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
2501 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
2505 dumpVGAReg();
2507 return 0;
2509 error_1:
2510 iounmap(xgi_video_info.mmio_vbase);
2511 iounmap(xgi_video_info.video_vbase);
2512 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2513 error_0:
2514 release_mem_region(xgi_video_info.video_base,
2515 xgi_video_info.video_size);
2516 error:
2517 vfree(XGIhw_ext.pjVirtualRomBase);
2518 framebuffer_release(fb_info);
2519 return ret;
2522 /*****************************************************/
2523 /* PCI DEVICE HANDLING */
2524 /*****************************************************/
2526 static void __devexit xgifb_remove(struct pci_dev *pdev)
2528 unregister_framebuffer(fb_info);
2529 iounmap(xgi_video_info.mmio_vbase);
2530 iounmap(xgi_video_info.video_vbase);
2531 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
2532 release_mem_region(xgi_video_info.video_base,
2533 xgi_video_info.video_size);
2534 vfree(XGIhw_ext.pjVirtualRomBase);
2535 framebuffer_release(fb_info);
2536 pci_set_drvdata(pdev, NULL);
2539 static struct pci_driver xgifb_driver = {
2540 .name = "xgifb",
2541 .id_table = xgifb_pci_table,
2542 .probe = xgifb_probe,
2543 .remove = __devexit_p(xgifb_remove)
2546 XGIINITSTATIC int __init xgifb_init(void)
2548 char *option = NULL;
2550 if (fb_get_options("xgifb", &option))
2551 return -ENODEV;
2552 XGIfb_setup(option);
2554 return pci_register_driver(&xgifb_driver);
2557 #ifndef MODULE
2558 module_init(xgifb_init);
2559 #endif
2561 /*****************************************************/
2562 /* MODULE */
2563 /*****************************************************/
2565 #ifdef MODULE
2567 static char *mode = NULL;
2568 static int vesa = 0;
2569 static unsigned int rate = 0;
2570 static unsigned int mem = 0;
2571 static char *forcecrt2type = NULL;
2572 static int forcecrt1 = -1;
2573 static int pdc = -1;
2574 static int pdc1 = -1;
2575 static int noypan = -1;
2576 static int userom = -1;
2577 static int useoem = -1;
2578 static char *tvstandard = NULL;
2579 static int nocrt2rate = 0;
2580 static int scalelcd = -1;
2581 static char *specialtiming = NULL;
2582 static int lvdshl = -1;
2583 static int tvxposoffset = 0, tvyposoffset = 0;
2584 #if !defined(__i386__) && !defined(__x86_64__)
2585 static int resetcard = 0;
2586 static int videoram = 0;
2587 #endif
2589 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2590 MODULE_LICENSE("GPL");
2591 MODULE_AUTHOR("XGITECH , Others");
2593 module_param(mem, int, 0);
2594 module_param(noypan, int, 0);
2595 module_param(userom, int, 0);
2596 module_param(useoem, int, 0);
2597 module_param(mode, charp, 0);
2598 module_param(vesa, int, 0);
2599 module_param(rate, int, 0);
2600 module_param(forcecrt1, int, 0);
2601 module_param(forcecrt2type, charp, 0);
2602 module_param(scalelcd, int, 0);
2603 module_param(pdc, int, 0);
2604 module_param(pdc1, int, 0);
2605 module_param(specialtiming, charp, 0);
2606 module_param(lvdshl, int, 0);
2607 module_param(tvstandard, charp, 0);
2608 module_param(tvxposoffset, int, 0);
2609 module_param(tvyposoffset, int, 0);
2610 module_param(filter, int, 0);
2611 module_param(nocrt2rate, int, 0);
2612 #if !defined(__i386__) && !defined(__x86_64__)
2613 module_param(resetcard, int, 0);
2614 module_param(videoram, int, 0);
2615 #endif
2617 MODULE_PARM_DESC(noypan,
2618 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
2619 "will be performed by redrawing the screen. (default: 0)\n");
2621 MODULE_PARM_DESC(mode,
2622 "\nSelects the desired default display mode in the format XxYxDepth,\n"
2623 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
2624 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
2625 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
2627 MODULE_PARM_DESC(vesa,
2628 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
2629 "0x117 (default: 0x0103)\n");
2631 MODULE_PARM_DESC(rate,
2632 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
2633 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
2634 "will be ignored (default: 60)\n");
2636 MODULE_PARM_DESC(forcecrt1,
2637 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is\n"
2638 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
2639 "0=CRT1 OFF) (default: [autodetected])\n");
2641 MODULE_PARM_DESC(forcecrt2type,
2642 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
2643 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
2644 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
2645 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
2646 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
2647 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
2648 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
2649 "depends on the very hardware in use. (default: [autodetected])\n");
2651 MODULE_PARM_DESC(scalelcd,
2652 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
2653 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
2654 "show black bars around the image, TMDS panels will probably do the scaling\n"
2655 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
2657 MODULE_PARM_DESC(pdc,
2658 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
2659 "should detect this correctly in most cases; however, sometimes this is not\n"
2660 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
2661 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
2662 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
2663 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
2665 MODULE_PARM_DESC(pdc1,
2666 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
2667 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
2668 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
2669 "implemented yet.\n");
2671 MODULE_PARM_DESC(specialtiming,
2672 "\nPlease refer to documentation for more information on this option.\n");
2674 MODULE_PARM_DESC(lvdshl,
2675 "\nPlease refer to documentation for more information on this option.\n");
2677 MODULE_PARM_DESC(tvstandard,
2678 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
2679 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
2681 MODULE_PARM_DESC(tvxposoffset,
2682 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
2683 "Default: 0\n");
2685 MODULE_PARM_DESC(tvyposoffset,
2686 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
2687 "Default: 0\n");
2689 MODULE_PARM_DESC(filter,
2690 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2691 "(Possible values 0-7, default: [no filter])\n");
2693 MODULE_PARM_DESC(nocrt2rate,
2694 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
2695 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
2697 static int __init xgifb_init_module(void)
2699 printk("\nXGIfb_init_module");
2700 if (mode)
2701 XGIfb_search_mode(mode);
2702 else if (vesa != -1)
2703 XGIfb_search_vesamode(vesa);
2705 return xgifb_init();
2708 static void __exit xgifb_remove_module(void)
2710 pci_unregister_driver(&xgifb_driver);
2711 printk(KERN_DEBUG "xgifb: Module unloaded\n");
2714 module_init(xgifb_init_module);
2715 module_exit(xgifb_remove_module);
2717 #endif /* /MODULE */