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