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