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