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