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