xref: /openbmc/linux/drivers/video/fbdev/core/fbmon.c (revision d2ba09c1)
1 /*
2  * linux/drivers/video/fbmon.c
3  *
4  * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
5  *
6  * Credits:
7  *
8  * The EDID Parser is a conglomeration from the following sources:
9  *
10  *   1. SciTech SNAP Graphics Architecture
11  *      Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
12  *
13  *   2. XFree86 4.3.0, interpret_edid.c
14  *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
15  *
16  *   3. John Fremlin <vii@users.sourceforge.net> and
17  *      Ani Joshi <ajoshi@unixbox.com>
18  *
19  * Generalized Timing Formula is derived from:
20  *
21  *      GTF Spreadsheet by Andy Morrish (1/5/97)
22  *      available at http://www.vesa.org
23  *
24  * This file is subject to the terms and conditions of the GNU General Public
25  * License.  See the file COPYING in the main directory of this archive
26  * for more details.
27  *
28  */
29 #include <linux/fb.h>
30 #include <linux/module.h>
31 #include <linux/pci.h>
32 #include <linux/slab.h>
33 #include <video/edid.h>
34 #include <video/of_videomode.h>
35 #include <video/videomode.h>
36 #include "../edid.h"
37 
38 /*
39  * EDID parser
40  */
41 
42 #undef DEBUG  /* define this for verbose EDID parsing output */
43 
44 #ifdef DEBUG
45 #define DPRINTK(fmt, args...) printk(fmt,## args)
46 #else
47 #define DPRINTK(fmt, args...)
48 #endif
49 
50 #define FBMON_FIX_HEADER  1
51 #define FBMON_FIX_INPUT   2
52 #define FBMON_FIX_TIMINGS 3
53 
54 #ifdef CONFIG_FB_MODE_HELPERS
55 struct broken_edid {
56 	u8  manufacturer[4];
57 	u32 model;
58 	u32 fix;
59 };
60 
61 static const struct broken_edid brokendb[] = {
62 	/* DEC FR-PCXAV-YZ */
63 	{
64 		.manufacturer = "DEC",
65 		.model        = 0x073a,
66 		.fix          = FBMON_FIX_HEADER,
67 	},
68 	/* ViewSonic PF775a */
69 	{
70 		.manufacturer = "VSC",
71 		.model        = 0x5a44,
72 		.fix          = FBMON_FIX_INPUT,
73 	},
74 	/* Sharp UXGA? */
75 	{
76 		.manufacturer = "SHP",
77 		.model        = 0x138e,
78 		.fix          = FBMON_FIX_TIMINGS,
79 	},
80 };
81 
82 static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
83 	0xff, 0xff, 0xff, 0x00
84 };
85 
86 static void copy_string(unsigned char *c, unsigned char *s)
87 {
88   int i;
89   c = c + 5;
90   for (i = 0; (i < 13 && *c != 0x0A); i++)
91     *(s++) = *(c++);
92   *s = 0;
93   while (i-- && (*--s == 0x20)) *s = 0;
94 }
95 
96 static int edid_is_serial_block(unsigned char *block)
97 {
98 	if ((block[0] == 0x00) && (block[1] == 0x00) &&
99 	    (block[2] == 0x00) && (block[3] == 0xff) &&
100 	    (block[4] == 0x00))
101 		return 1;
102 	else
103 		return 0;
104 }
105 
106 static int edid_is_ascii_block(unsigned char *block)
107 {
108 	if ((block[0] == 0x00) && (block[1] == 0x00) &&
109 	    (block[2] == 0x00) && (block[3] == 0xfe) &&
110 	    (block[4] == 0x00))
111 		return 1;
112 	else
113 		return 0;
114 }
115 
116 static int edid_is_limits_block(unsigned char *block)
117 {
118 	if ((block[0] == 0x00) && (block[1] == 0x00) &&
119 	    (block[2] == 0x00) && (block[3] == 0xfd) &&
120 	    (block[4] == 0x00))
121 		return 1;
122 	else
123 		return 0;
124 }
125 
126 static int edid_is_monitor_block(unsigned char *block)
127 {
128 	if ((block[0] == 0x00) && (block[1] == 0x00) &&
129 	    (block[2] == 0x00) && (block[3] == 0xfc) &&
130 	    (block[4] == 0x00))
131 		return 1;
132 	else
133 		return 0;
134 }
135 
136 static int edid_is_timing_block(unsigned char *block)
137 {
138 	if ((block[0] != 0x00) || (block[1] != 0x00) ||
139 	    (block[2] != 0x00) || (block[4] != 0x00))
140 		return 1;
141 	else
142 		return 0;
143 }
144 
145 static int check_edid(unsigned char *edid)
146 {
147 	unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
148 	unsigned char *b;
149 	u32 model;
150 	int i, fix = 0, ret = 0;
151 
152 	manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
153 	manufacturer[1] = ((block[0] & 0x03) << 3) +
154 		((block[1] & 0xe0) >> 5) + '@';
155 	manufacturer[2] = (block[1] & 0x1f) + '@';
156 	manufacturer[3] = 0;
157 	model = block[2] + (block[3] << 8);
158 
159 	for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
160 		if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
161 			brokendb[i].model == model) {
162 			fix = brokendb[i].fix;
163 			break;
164 		}
165 	}
166 
167 	switch (fix) {
168 	case FBMON_FIX_HEADER:
169 		for (i = 0; i < 8; i++) {
170 			if (edid[i] != edid_v1_header[i]) {
171 				ret = fix;
172 				break;
173 			}
174 		}
175 		break;
176 	case FBMON_FIX_INPUT:
177 		b = edid + EDID_STRUCT_DISPLAY;
178 		/* Only if display is GTF capable will
179 		   the input type be reset to analog */
180 		if (b[4] & 0x01 && b[0] & 0x80)
181 			ret = fix;
182 		break;
183 	case FBMON_FIX_TIMINGS:
184 		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
185 		ret = fix;
186 
187 		for (i = 0; i < 4; i++) {
188 			if (edid_is_limits_block(b)) {
189 				ret = 0;
190 				break;
191 			}
192 
193 			b += DETAILED_TIMING_DESCRIPTION_SIZE;
194 		}
195 
196 		break;
197 	}
198 
199 	if (ret)
200 		printk("fbmon: The EDID Block of "
201 		       "Manufacturer: %s Model: 0x%x is known to "
202 		       "be broken,\n",  manufacturer, model);
203 
204 	return ret;
205 }
206 
207 static void fix_edid(unsigned char *edid, int fix)
208 {
209 	int i;
210 	unsigned char *b, csum = 0;
211 
212 	switch (fix) {
213 	case FBMON_FIX_HEADER:
214 		printk("fbmon: trying a header reconstruct\n");
215 		memcpy(edid, edid_v1_header, 8);
216 		break;
217 	case FBMON_FIX_INPUT:
218 		printk("fbmon: trying to fix input type\n");
219 		b = edid + EDID_STRUCT_DISPLAY;
220 		b[0] &= ~0x80;
221 		edid[127] += 0x80;
222 		break;
223 	case FBMON_FIX_TIMINGS:
224 		printk("fbmon: trying to fix monitor timings\n");
225 		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
226 		for (i = 0; i < 4; i++) {
227 			if (!(edid_is_serial_block(b) ||
228 			      edid_is_ascii_block(b) ||
229 			      edid_is_monitor_block(b) ||
230 			      edid_is_timing_block(b))) {
231 				b[0] = 0x00;
232 				b[1] = 0x00;
233 				b[2] = 0x00;
234 				b[3] = 0xfd;
235 				b[4] = 0x00;
236 				b[5] = 60;   /* vfmin */
237 				b[6] = 60;   /* vfmax */
238 				b[7] = 30;   /* hfmin */
239 				b[8] = 75;   /* hfmax */
240 				b[9] = 17;   /* pixclock - 170 MHz*/
241 				b[10] = 0;   /* GTF */
242 				break;
243 			}
244 
245 			b += DETAILED_TIMING_DESCRIPTION_SIZE;
246 		}
247 
248 		for (i = 0; i < EDID_LENGTH - 1; i++)
249 			csum += edid[i];
250 
251 		edid[127] = 256 - csum;
252 		break;
253 	}
254 }
255 
256 static int edid_checksum(unsigned char *edid)
257 {
258 	unsigned char csum = 0, all_null = 0;
259 	int i, err = 0, fix = check_edid(edid);
260 
261 	if (fix)
262 		fix_edid(edid, fix);
263 
264 	for (i = 0; i < EDID_LENGTH; i++) {
265 		csum += edid[i];
266 		all_null |= edid[i];
267 	}
268 
269 	if (csum == 0x00 && all_null) {
270 		/* checksum passed, everything's good */
271 		err = 1;
272 	}
273 
274 	return err;
275 }
276 
277 static int edid_check_header(unsigned char *edid)
278 {
279 	int i, err = 1, fix = check_edid(edid);
280 
281 	if (fix)
282 		fix_edid(edid, fix);
283 
284 	for (i = 0; i < 8; i++) {
285 		if (edid[i] != edid_v1_header[i])
286 			err = 0;
287 	}
288 
289 	return err;
290 }
291 
292 static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs)
293 {
294 	specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
295 	specs->manufacturer[1] = ((block[0] & 0x03) << 3) +
296 		((block[1] & 0xe0) >> 5) + '@';
297 	specs->manufacturer[2] = (block[1] & 0x1f) + '@';
298 	specs->manufacturer[3] = 0;
299 	specs->model = block[2] + (block[3] << 8);
300 	specs->serial = block[4] + (block[5] << 8) +
301 	       (block[6] << 16) + (block[7] << 24);
302 	specs->year = block[9] + 1990;
303 	specs->week = block[8];
304 	DPRINTK("   Manufacturer: %s\n", specs->manufacturer);
305 	DPRINTK("   Model: %x\n", specs->model);
306 	DPRINTK("   Serial#: %u\n", specs->serial);
307 	DPRINTK("   Year: %u Week %u\n", specs->year, specs->week);
308 }
309 
310 static void get_dpms_capabilities(unsigned char flags,
311 				  struct fb_monspecs *specs)
312 {
313 	specs->dpms = 0;
314 	if (flags & DPMS_ACTIVE_OFF)
315 		specs->dpms |= FB_DPMS_ACTIVE_OFF;
316 	if (flags & DPMS_SUSPEND)
317 		specs->dpms |= FB_DPMS_SUSPEND;
318 	if (flags & DPMS_STANDBY)
319 		specs->dpms |= FB_DPMS_STANDBY;
320 	DPRINTK("      DPMS: Active %s, Suspend %s, Standby %s\n",
321 	       (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
322 	       (flags & DPMS_SUSPEND)    ? "yes" : "no",
323 	       (flags & DPMS_STANDBY)    ? "yes" : "no");
324 }
325 
326 static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
327 {
328 	int tmp;
329 
330 	DPRINTK("      Chroma\n");
331 	/* Chromaticity data */
332 	tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
333 	tmp *= 1000;
334 	tmp += 512;
335 	specs->chroma.redx = tmp/1024;
336 	DPRINTK("         RedX:     0.%03d ", specs->chroma.redx);
337 
338 	tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
339 	tmp *= 1000;
340 	tmp += 512;
341 	specs->chroma.redy = tmp/1024;
342 	DPRINTK("RedY:     0.%03d\n", specs->chroma.redy);
343 
344 	tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
345 	tmp *= 1000;
346 	tmp += 512;
347 	specs->chroma.greenx = tmp/1024;
348 	DPRINTK("         GreenX:   0.%03d ", specs->chroma.greenx);
349 
350 	tmp = (block[5] & 3) | (block[0xa] << 2);
351 	tmp *= 1000;
352 	tmp += 512;
353 	specs->chroma.greeny = tmp/1024;
354 	DPRINTK("GreenY:   0.%03d\n", specs->chroma.greeny);
355 
356 	tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
357 	tmp *= 1000;
358 	tmp += 512;
359 	specs->chroma.bluex = tmp/1024;
360 	DPRINTK("         BlueX:    0.%03d ", specs->chroma.bluex);
361 
362 	tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
363 	tmp *= 1000;
364 	tmp += 512;
365 	specs->chroma.bluey = tmp/1024;
366 	DPRINTK("BlueY:    0.%03d\n", specs->chroma.bluey);
367 
368 	tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
369 	tmp *= 1000;
370 	tmp += 512;
371 	specs->chroma.whitex = tmp/1024;
372 	DPRINTK("         WhiteX:   0.%03d ", specs->chroma.whitex);
373 
374 	tmp = (block[6] & 3) | (block[0xe] << 2);
375 	tmp *= 1000;
376 	tmp += 512;
377 	specs->chroma.whitey = tmp/1024;
378 	DPRINTK("WhiteY:   0.%03d\n", specs->chroma.whitey);
379 }
380 
381 static void calc_mode_timings(int xres, int yres, int refresh,
382 			      struct fb_videomode *mode)
383 {
384 	struct fb_var_screeninfo *var;
385 
386 	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
387 
388 	if (var) {
389 		var->xres = xres;
390 		var->yres = yres;
391 		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
392 			    refresh, var, NULL);
393 		mode->xres = xres;
394 		mode->yres = yres;
395 		mode->pixclock = var->pixclock;
396 		mode->refresh = refresh;
397 		mode->left_margin = var->left_margin;
398 		mode->right_margin = var->right_margin;
399 		mode->upper_margin = var->upper_margin;
400 		mode->lower_margin = var->lower_margin;
401 		mode->hsync_len = var->hsync_len;
402 		mode->vsync_len = var->vsync_len;
403 		mode->vmode = 0;
404 		mode->sync = 0;
405 		kfree(var);
406 	}
407 }
408 
409 static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
410 {
411 	int num = 0;
412 	unsigned char c;
413 
414 	c = block[0];
415 	if (c&0x80) {
416 		calc_mode_timings(720, 400, 70, &mode[num]);
417 		mode[num++].flag = FB_MODE_IS_CALCULATED;
418 		DPRINTK("      720x400@70Hz\n");
419 	}
420 	if (c&0x40) {
421 		calc_mode_timings(720, 400, 88, &mode[num]);
422 		mode[num++].flag = FB_MODE_IS_CALCULATED;
423 		DPRINTK("      720x400@88Hz\n");
424 	}
425 	if (c&0x20) {
426 		mode[num++] = vesa_modes[3];
427 		DPRINTK("      640x480@60Hz\n");
428 	}
429 	if (c&0x10) {
430 		calc_mode_timings(640, 480, 67, &mode[num]);
431 		mode[num++].flag = FB_MODE_IS_CALCULATED;
432 		DPRINTK("      640x480@67Hz\n");
433 	}
434 	if (c&0x08) {
435 		mode[num++] = vesa_modes[4];
436 		DPRINTK("      640x480@72Hz\n");
437 	}
438 	if (c&0x04) {
439 		mode[num++] = vesa_modes[5];
440 		DPRINTK("      640x480@75Hz\n");
441 	}
442 	if (c&0x02) {
443 		mode[num++] = vesa_modes[7];
444 		DPRINTK("      800x600@56Hz\n");
445 	}
446 	if (c&0x01) {
447 		mode[num++] = vesa_modes[8];
448 		DPRINTK("      800x600@60Hz\n");
449 	}
450 
451 	c = block[1];
452 	if (c&0x80) {
453 		mode[num++] = vesa_modes[9];
454 		DPRINTK("      800x600@72Hz\n");
455 	}
456 	if (c&0x40) {
457 		mode[num++] = vesa_modes[10];
458 		DPRINTK("      800x600@75Hz\n");
459 	}
460 	if (c&0x20) {
461 		calc_mode_timings(832, 624, 75, &mode[num]);
462 		mode[num++].flag = FB_MODE_IS_CALCULATED;
463 		DPRINTK("      832x624@75Hz\n");
464 	}
465 	if (c&0x10) {
466 		mode[num++] = vesa_modes[12];
467 		DPRINTK("      1024x768@87Hz Interlaced\n");
468 	}
469 	if (c&0x08) {
470 		mode[num++] = vesa_modes[13];
471 		DPRINTK("      1024x768@60Hz\n");
472 	}
473 	if (c&0x04) {
474 		mode[num++] = vesa_modes[14];
475 		DPRINTK("      1024x768@70Hz\n");
476 	}
477 	if (c&0x02) {
478 		mode[num++] = vesa_modes[15];
479 		DPRINTK("      1024x768@75Hz\n");
480 	}
481 	if (c&0x01) {
482 		mode[num++] = vesa_modes[21];
483 		DPRINTK("      1280x1024@75Hz\n");
484 	}
485 	c = block[2];
486 	if (c&0x80) {
487 		mode[num++] = vesa_modes[17];
488 		DPRINTK("      1152x870@75Hz\n");
489 	}
490 	DPRINTK("      Manufacturer's mask: %x\n",c&0x7F);
491 	return num;
492 }
493 
494 static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
495 			  int ver, int rev, const struct fb_monspecs *specs)
496 {
497 	int i;
498 
499 	for (i = 0; i < DMT_SIZE; i++) {
500 		u32 std_2byte_code = block[0] << 8 | block[1];
501 		if (std_2byte_code == dmt_modes[i].std_2byte_code)
502 			break;
503 	}
504 
505 	if (i < DMT_SIZE && dmt_modes[i].mode) {
506 		/* DMT mode found */
507 		*mode = *dmt_modes[i].mode;
508 		mode->flag |= FB_MODE_IS_STANDARD;
509 		DPRINTK("        DMT id=%d\n", dmt_modes[i].dmt_id);
510 
511 	} else {
512 		int xres, yres = 0, refresh, ratio;
513 
514 		xres = (block[0] + 31) * 8;
515 		if (xres <= 256)
516 			return 0;
517 
518 		ratio = (block[1] & 0xc0) >> 6;
519 		switch (ratio) {
520 		case 0:
521 			/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
522 			if (ver < 1 || (ver == 1 && rev < 3))
523 				yres = xres;
524 			else
525 				yres = (xres * 10)/16;
526 			break;
527 		case 1:
528 			yres = (xres * 3)/4;
529 			break;
530 		case 2:
531 			yres = (xres * 4)/5;
532 			break;
533 		case 3:
534 			yres = (xres * 9)/16;
535 			break;
536 		}
537 		refresh = (block[1] & 0x3f) + 60;
538 		DPRINTK("      %dx%d@%dHz\n", xres, yres, refresh);
539 
540 		calc_mode_timings(xres, yres, refresh, mode);
541 	}
542 
543 	/* Check the mode we got is within valid spec of the monitor */
544 	if (specs && specs->dclkmax
545 	    && PICOS2KHZ(mode->pixclock) * 1000 > specs->dclkmax) {
546 		DPRINTK("        mode exceed max DCLK\n");
547 		return 0;
548 	}
549 
550 	return 1;
551 }
552 
553 static int get_dst_timing(unsigned char *block, struct fb_videomode *mode,
554 			  int ver, int rev, const struct fb_monspecs *specs)
555 {
556 	int j, num = 0;
557 
558 	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
559 		num += get_std_timing(block, &mode[num], ver, rev, specs);
560 
561 	return num;
562 }
563 
564 static void get_detailed_timing(unsigned char *block,
565 				struct fb_videomode *mode)
566 {
567 	mode->xres = H_ACTIVE;
568 	mode->yres = V_ACTIVE;
569 	mode->pixclock = PIXEL_CLOCK;
570 	mode->pixclock /= 1000;
571 	mode->pixclock = KHZ2PICOS(mode->pixclock);
572 	mode->right_margin = H_SYNC_OFFSET;
573 	mode->left_margin = (H_ACTIVE + H_BLANKING) -
574 		(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
575 	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
576 		V_SYNC_WIDTH;
577 	mode->lower_margin = V_SYNC_OFFSET;
578 	mode->hsync_len = H_SYNC_WIDTH;
579 	mode->vsync_len = V_SYNC_WIDTH;
580 	if (HSYNC_POSITIVE)
581 		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
582 	if (VSYNC_POSITIVE)
583 		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
584 	mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
585 				     (V_ACTIVE + V_BLANKING));
586 	if (INTERLACED) {
587 		mode->yres *= 2;
588 		mode->upper_margin *= 2;
589 		mode->lower_margin *= 2;
590 		mode->vsync_len *= 2;
591 		mode->vmode |= FB_VMODE_INTERLACED;
592 	}
593 	mode->flag = FB_MODE_IS_DETAILED;
594 
595 	DPRINTK("      %d MHz ",  PIXEL_CLOCK/1000000);
596 	DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
597 	       H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
598 	DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
599 	       V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
600 	DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
601 	       (VSYNC_POSITIVE) ? "+" : "-");
602 }
603 
604 /**
605  * fb_create_modedb - create video mode database
606  * @edid: EDID data
607  * @dbsize: database size
608  *
609  * RETURNS: struct fb_videomode, @dbsize contains length of database
610  *
611  * DESCRIPTION:
612  * This function builds a mode database using the contents of the EDID
613  * data
614  */
615 static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize,
616 					     const struct fb_monspecs *specs)
617 {
618 	struct fb_videomode *mode, *m;
619 	unsigned char *block;
620 	int num = 0, i, first = 1;
621 	int ver, rev;
622 
623 	mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
624 	if (mode == NULL)
625 		return NULL;
626 
627 	if (edid == NULL || !edid_checksum(edid) ||
628 	    !edid_check_header(edid)) {
629 		kfree(mode);
630 		return NULL;
631 	}
632 
633 	ver = edid[EDID_STRUCT_VERSION];
634 	rev = edid[EDID_STRUCT_REVISION];
635 
636 	*dbsize = 0;
637 
638 	DPRINTK("   Detailed Timings\n");
639 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
640 	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
641 		if (!(block[0] == 0x00 && block[1] == 0x00)) {
642 			get_detailed_timing(block, &mode[num]);
643 			if (first) {
644 			        mode[num].flag |= FB_MODE_IS_FIRST;
645 				first = 0;
646 			}
647 			num++;
648 		}
649 	}
650 
651 	DPRINTK("   Supported VESA Modes\n");
652 	block = edid + ESTABLISHED_TIMING_1;
653 	num += get_est_timing(block, &mode[num]);
654 
655 	DPRINTK("   Standard Timings\n");
656 	block = edid + STD_TIMING_DESCRIPTIONS_START;
657 	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
658 		num += get_std_timing(block, &mode[num], ver, rev, specs);
659 
660 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
661 	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
662 		if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
663 			num += get_dst_timing(block + 5, &mode[num],
664 					      ver, rev, specs);
665 	}
666 
667 	/* Yikes, EDID data is totally useless */
668 	if (!num) {
669 		kfree(mode);
670 		return NULL;
671 	}
672 
673 	*dbsize = num;
674 	m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
675 	if (!m)
676 		return mode;
677 	memmove(m, mode, num * sizeof(struct fb_videomode));
678 	kfree(mode);
679 	return m;
680 }
681 
682 /**
683  * fb_destroy_modedb - destroys mode database
684  * @modedb: mode database to destroy
685  *
686  * DESCRIPTION:
687  * Destroy mode database created by fb_create_modedb
688  */
689 void fb_destroy_modedb(struct fb_videomode *modedb)
690 {
691 	kfree(modedb);
692 }
693 
694 static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
695 {
696 	int i, retval = 1;
697 	unsigned char *block;
698 
699 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
700 
701 	DPRINTK("      Monitor Operating Limits: ");
702 
703 	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
704 		if (edid_is_limits_block(block)) {
705 			specs->hfmin = H_MIN_RATE * 1000;
706 			specs->hfmax = H_MAX_RATE * 1000;
707 			specs->vfmin = V_MIN_RATE;
708 			specs->vfmax = V_MAX_RATE;
709 			specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
710 			specs->gtf = (GTF_SUPPORT) ? 1 : 0;
711 			retval = 0;
712 			DPRINTK("From EDID\n");
713 			break;
714 		}
715 	}
716 
717 	/* estimate monitor limits based on modes supported */
718 	if (retval) {
719 		struct fb_videomode *modes, *mode;
720 		int num_modes, hz, hscan, pixclock;
721 		int vtotal, htotal;
722 
723 		modes = fb_create_modedb(edid, &num_modes, specs);
724 		if (!modes) {
725 			DPRINTK("None Available\n");
726 			return 1;
727 		}
728 
729 		retval = 0;
730 		for (i = 0; i < num_modes; i++) {
731 			mode = &modes[i];
732 			pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
733 			htotal = mode->xres + mode->right_margin + mode->hsync_len
734 				+ mode->left_margin;
735 			vtotal = mode->yres + mode->lower_margin + mode->vsync_len
736 				+ mode->upper_margin;
737 
738 			if (mode->vmode & FB_VMODE_INTERLACED)
739 				vtotal /= 2;
740 
741 			if (mode->vmode & FB_VMODE_DOUBLE)
742 				vtotal *= 2;
743 
744 			hscan = (pixclock + htotal / 2) / htotal;
745 			hscan = (hscan + 500) / 1000 * 1000;
746 			hz = (hscan + vtotal / 2) / vtotal;
747 
748 			if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
749 				specs->dclkmax = pixclock;
750 
751 			if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
752 				specs->dclkmin = pixclock;
753 
754 			if (specs->hfmax == 0 || specs->hfmax < hscan)
755 				specs->hfmax = hscan;
756 
757 			if (specs->hfmin == 0 || specs->hfmin > hscan)
758 				specs->hfmin = hscan;
759 
760 			if (specs->vfmax == 0 || specs->vfmax < hz)
761 				specs->vfmax = hz;
762 
763 			if (specs->vfmin == 0 || specs->vfmin > hz)
764 				specs->vfmin = hz;
765 		}
766 		DPRINTK("Extrapolated\n");
767 		fb_destroy_modedb(modes);
768 	}
769 	DPRINTK("           H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
770 		specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
771 		specs->vfmax, specs->dclkmax/1000000);
772 	return retval;
773 }
774 
775 static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
776 {
777 	unsigned char c, *block;
778 
779 	block = edid + EDID_STRUCT_DISPLAY;
780 
781 	fb_get_monitor_limits(edid, specs);
782 
783 	c = block[0] & 0x80;
784 	specs->input = 0;
785 	if (c) {
786 		specs->input |= FB_DISP_DDI;
787 		DPRINTK("      Digital Display Input");
788 	} else {
789 		DPRINTK("      Analog Display Input: Input Voltage - ");
790 		switch ((block[0] & 0x60) >> 5) {
791 		case 0:
792 			DPRINTK("0.700V/0.300V");
793 			specs->input |= FB_DISP_ANA_700_300;
794 			break;
795 		case 1:
796 			DPRINTK("0.714V/0.286V");
797 			specs->input |= FB_DISP_ANA_714_286;
798 			break;
799 		case 2:
800 			DPRINTK("1.000V/0.400V");
801 			specs->input |= FB_DISP_ANA_1000_400;
802 			break;
803 		case 3:
804 			DPRINTK("0.700V/0.000V");
805 			specs->input |= FB_DISP_ANA_700_000;
806 			break;
807 		}
808 	}
809 	DPRINTK("\n      Sync: ");
810 	c = block[0] & 0x10;
811 	if (c)
812 		DPRINTK("      Configurable signal level\n");
813 	c = block[0] & 0x0f;
814 	specs->signal = 0;
815 	if (c & 0x10) {
816 		DPRINTK("Blank to Blank ");
817 		specs->signal |= FB_SIGNAL_BLANK_BLANK;
818 	}
819 	if (c & 0x08) {
820 		DPRINTK("Separate ");
821 		specs->signal |= FB_SIGNAL_SEPARATE;
822 	}
823 	if (c & 0x04) {
824 		DPRINTK("Composite ");
825 		specs->signal |= FB_SIGNAL_COMPOSITE;
826 	}
827 	if (c & 0x02) {
828 		DPRINTK("Sync on Green ");
829 		specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
830 	}
831 	if (c & 0x01) {
832 		DPRINTK("Serration on ");
833 		specs->signal |= FB_SIGNAL_SERRATION_ON;
834 	}
835 	DPRINTK("\n");
836 	specs->max_x = block[1];
837 	specs->max_y = block[2];
838 	DPRINTK("      Max H-size in cm: ");
839 	if (specs->max_x)
840 		DPRINTK("%d\n", specs->max_x);
841 	else
842 		DPRINTK("variable\n");
843 	DPRINTK("      Max V-size in cm: ");
844 	if (specs->max_y)
845 		DPRINTK("%d\n", specs->max_y);
846 	else
847 		DPRINTK("variable\n");
848 
849 	c = block[3];
850 	specs->gamma = c+100;
851 	DPRINTK("      Gamma: ");
852 	DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
853 
854 	get_dpms_capabilities(block[4], specs);
855 
856 	switch ((block[4] & 0x18) >> 3) {
857 	case 0:
858 		DPRINTK("      Monochrome/Grayscale\n");
859 		specs->input |= FB_DISP_MONO;
860 		break;
861 	case 1:
862 		DPRINTK("      RGB Color Display\n");
863 		specs->input |= FB_DISP_RGB;
864 		break;
865 	case 2:
866 		DPRINTK("      Non-RGB Multicolor Display\n");
867 		specs->input |= FB_DISP_MULTI;
868 		break;
869 	default:
870 		DPRINTK("      Unknown\n");
871 		specs->input |= FB_DISP_UNKNOWN;
872 		break;
873 	}
874 
875 	get_chroma(block, specs);
876 
877 	specs->misc = 0;
878 	c = block[4] & 0x7;
879 	if (c & 0x04) {
880 		DPRINTK("      Default color format is primary\n");
881 		specs->misc |= FB_MISC_PRIM_COLOR;
882 	}
883 	if (c & 0x02) {
884 		DPRINTK("      First DETAILED Timing is preferred\n");
885 		specs->misc |= FB_MISC_1ST_DETAIL;
886 	}
887 	if (c & 0x01) {
888 		printk("      Display is GTF capable\n");
889 		specs->gtf = 1;
890 	}
891 }
892 
893 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
894 {
895 	int i;
896 	unsigned char *block;
897 
898 	if (edid == NULL || var == NULL)
899 		return 1;
900 
901 	if (!(edid_checksum(edid)))
902 		return 1;
903 
904 	if (!(edid_check_header(edid)))
905 		return 1;
906 
907 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
908 
909 	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
910 		if (edid_is_timing_block(block)) {
911 			var->xres = var->xres_virtual = H_ACTIVE;
912 			var->yres = var->yres_virtual = V_ACTIVE;
913 			var->height = var->width = 0;
914 			var->right_margin = H_SYNC_OFFSET;
915 			var->left_margin = (H_ACTIVE + H_BLANKING) -
916 				(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
917 			var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
918 				V_SYNC_WIDTH;
919 			var->lower_margin = V_SYNC_OFFSET;
920 			var->hsync_len = H_SYNC_WIDTH;
921 			var->vsync_len = V_SYNC_WIDTH;
922 			var->pixclock = PIXEL_CLOCK;
923 			var->pixclock /= 1000;
924 			var->pixclock = KHZ2PICOS(var->pixclock);
925 
926 			if (HSYNC_POSITIVE)
927 				var->sync |= FB_SYNC_HOR_HIGH_ACT;
928 			if (VSYNC_POSITIVE)
929 				var->sync |= FB_SYNC_VERT_HIGH_ACT;
930 			return 0;
931 		}
932 	}
933 	return 1;
934 }
935 
936 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
937 {
938 	unsigned char *block;
939 	int i, found = 0;
940 
941 	if (edid == NULL)
942 		return;
943 
944 	if (!(edid_checksum(edid)))
945 		return;
946 
947 	if (!(edid_check_header(edid)))
948 		return;
949 
950 	memset(specs, 0, sizeof(struct fb_monspecs));
951 
952 	specs->version = edid[EDID_STRUCT_VERSION];
953 	specs->revision = edid[EDID_STRUCT_REVISION];
954 
955 	DPRINTK("========================================\n");
956 	DPRINTK("Display Information (EDID)\n");
957 	DPRINTK("========================================\n");
958 	DPRINTK("   EDID Version %d.%d\n", (int) specs->version,
959 	       (int) specs->revision);
960 
961 	parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
962 
963 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
964 	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
965 		if (edid_is_serial_block(block)) {
966 			copy_string(block, specs->serial_no);
967 			DPRINTK("   Serial Number: %s\n", specs->serial_no);
968 		} else if (edid_is_ascii_block(block)) {
969 			copy_string(block, specs->ascii);
970 			DPRINTK("   ASCII Block: %s\n", specs->ascii);
971 		} else if (edid_is_monitor_block(block)) {
972 			copy_string(block, specs->monitor);
973 			DPRINTK("   Monitor Name: %s\n", specs->monitor);
974 		}
975 	}
976 
977 	DPRINTK("   Display Characteristics:\n");
978 	get_monspecs(edid, specs);
979 
980 	specs->modedb = fb_create_modedb(edid, &specs->modedb_len, specs);
981 
982 	/*
983 	 * Workaround for buggy EDIDs that sets that the first
984 	 * detailed timing is preferred but has not detailed
985 	 * timing specified
986 	 */
987 	for (i = 0; i < specs->modedb_len; i++) {
988 		if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
989 			found = 1;
990 			break;
991 		}
992 	}
993 
994 	if (!found)
995 		specs->misc &= ~FB_MISC_1ST_DETAIL;
996 
997 	DPRINTK("========================================\n");
998 }
999 
1000 /**
1001  * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
1002  * @edid:	128 byte array with an E-EDID block
1003  * @spacs:	monitor specs to be extended
1004  */
1005 void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1006 {
1007 	unsigned char *block;
1008 	struct fb_videomode *m;
1009 	int num = 0, i;
1010 	u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
1011 	u8 pos = 4, svd_n = 0;
1012 
1013 	if (!edid)
1014 		return;
1015 
1016 	if (!edid_checksum(edid))
1017 		return;
1018 
1019 	if (edid[0] != 0x2 ||
1020 	    edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
1021 		return;
1022 
1023 	DPRINTK("  Short Video Descriptors\n");
1024 
1025 	while (pos < edid[2]) {
1026 		u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
1027 		pr_debug("Data block %u of %u bytes\n", type, len);
1028 		if (type == 2) {
1029 			for (i = pos; i < pos + len; i++) {
1030 				u8 idx = edid[pos + i] & 0x7f;
1031 				svd[svd_n++] = idx;
1032 				pr_debug("N%sative mode #%d\n",
1033 					 edid[pos + i] & 0x80 ? "" : "on-n", idx);
1034 			}
1035 		} else if (type == 3 && len >= 3) {
1036 			/* Check Vendor Specific Data Block.  For HDMI,
1037 			   it is always 00-0C-03 for HDMI Licensing, LLC. */
1038 			if (edid[pos + 1] == 3 && edid[pos + 2] == 0xc &&
1039 			    edid[pos + 3] == 0)
1040 				specs->misc |= FB_MISC_HDMI;
1041 		}
1042 		pos += len + 1;
1043 	}
1044 
1045 	block = edid + edid[2];
1046 
1047 	DPRINTK("  Extended Detailed Timings\n");
1048 
1049 	for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
1050 	     i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
1051 		if (PIXEL_CLOCK != 0)
1052 			edt[num++] = block - edid;
1053 
1054 	/* Yikes, EDID data is totally useless */
1055 	if (!(num + svd_n))
1056 		return;
1057 
1058 	m = kzalloc((specs->modedb_len + num + svd_n) *
1059 		       sizeof(struct fb_videomode), GFP_KERNEL);
1060 
1061 	if (!m)
1062 		return;
1063 
1064 	memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
1065 
1066 	for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
1067 		get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
1068 		if (i == specs->modedb_len)
1069 			m[i].flag |= FB_MODE_IS_FIRST;
1070 		pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
1071 	}
1072 
1073 	for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
1074 		int idx = svd[i - specs->modedb_len - num];
1075 		if (!idx || idx >= ARRAY_SIZE(cea_modes)) {
1076 			pr_warn("Reserved SVD code %d\n", idx);
1077 		} else if (!cea_modes[idx].xres) {
1078 			pr_warn("Unimplemented SVD code %d\n", idx);
1079 		} else {
1080 			memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
1081 			pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
1082 				 m[i].xres, m[i].yres, m[i].refresh);
1083 		}
1084 	}
1085 
1086 	kfree(specs->modedb);
1087 	specs->modedb = m;
1088 	specs->modedb_len = specs->modedb_len + num + svd_n;
1089 }
1090 
1091 /*
1092  * VESA Generalized Timing Formula (GTF)
1093  */
1094 
1095 #define FLYBACK                     550
1096 #define V_FRONTPORCH                1
1097 #define H_OFFSET                    40
1098 #define H_SCALEFACTOR               20
1099 #define H_BLANKSCALE                128
1100 #define H_GRADIENT                  600
1101 #define C_VAL                       30
1102 #define M_VAL                       300
1103 
1104 struct __fb_timings {
1105 	u32 dclk;
1106 	u32 hfreq;
1107 	u32 vfreq;
1108 	u32 hactive;
1109 	u32 vactive;
1110 	u32 hblank;
1111 	u32 vblank;
1112 	u32 htotal;
1113 	u32 vtotal;
1114 };
1115 
1116 /**
1117  * fb_get_vblank - get vertical blank time
1118  * @hfreq: horizontal freq
1119  *
1120  * DESCRIPTION:
1121  * vblank = right_margin + vsync_len + left_margin
1122  *
1123  *    given: right_margin = 1 (V_FRONTPORCH)
1124  *           vsync_len    = 3
1125  *           flyback      = 550
1126  *
1127  *                          flyback * hfreq
1128  *           left_margin  = --------------- - vsync_len
1129  *                           1000000
1130  */
1131 static u32 fb_get_vblank(u32 hfreq)
1132 {
1133 	u32 vblank;
1134 
1135 	vblank = (hfreq * FLYBACK)/1000;
1136 	vblank = (vblank + 500)/1000;
1137 	return (vblank + V_FRONTPORCH);
1138 }
1139 
1140 /**
1141  * fb_get_hblank_by_freq - get horizontal blank time given hfreq
1142  * @hfreq: horizontal freq
1143  * @xres: horizontal resolution in pixels
1144  *
1145  * DESCRIPTION:
1146  *
1147  *           xres * duty_cycle
1148  * hblank = ------------------
1149  *           100 - duty_cycle
1150  *
1151  * duty cycle = percent of htotal assigned to inactive display
1152  * duty cycle = C - (M/Hfreq)
1153  *
1154  * where: C = ((offset - scale factor) * blank_scale)
1155  *            -------------------------------------- + scale factor
1156  *                        256
1157  *        M = blank_scale * gradient
1158  *
1159  */
1160 static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
1161 {
1162 	u32 c_val, m_val, duty_cycle, hblank;
1163 
1164 	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
1165 		 H_SCALEFACTOR) * 1000;
1166 	m_val = (H_BLANKSCALE * H_GRADIENT)/256;
1167 	m_val = (m_val * 1000000)/hfreq;
1168 	duty_cycle = c_val - m_val;
1169 	hblank = (xres * duty_cycle)/(100000 - duty_cycle);
1170 	return (hblank);
1171 }
1172 
1173 /**
1174  * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
1175  * @dclk: pixelclock in Hz
1176  * @xres: horizontal resolution in pixels
1177  *
1178  * DESCRIPTION:
1179  *
1180  *           xres * duty_cycle
1181  * hblank = ------------------
1182  *           100 - duty_cycle
1183  *
1184  * duty cycle = percent of htotal assigned to inactive display
1185  * duty cycle = C - (M * h_period)
1186  *
1187  * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
1188  *                   -----------------------------------------------
1189  *                                    2 * M
1190  *        M = 300;
1191  *        C = 30;
1192 
1193  */
1194 static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
1195 {
1196 	u32 duty_cycle, h_period, hblank;
1197 
1198 	dclk /= 1000;
1199 	h_period = 100 - C_VAL;
1200 	h_period *= h_period;
1201 	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
1202 	h_period *= 10000;
1203 
1204 	h_period = int_sqrt(h_period);
1205 	h_period -= (100 - C_VAL) * 100;
1206 	h_period *= 1000;
1207 	h_period /= 2 * M_VAL;
1208 
1209 	duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
1210 	hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
1211 	hblank &= ~15;
1212 	return (hblank);
1213 }
1214 
1215 /**
1216  * fb_get_hfreq - estimate hsync
1217  * @vfreq: vertical refresh rate
1218  * @yres: vertical resolution
1219  *
1220  * DESCRIPTION:
1221  *
1222  *          (yres + front_port) * vfreq * 1000000
1223  * hfreq = -------------------------------------
1224  *          (1000000 - (vfreq * FLYBACK)
1225  *
1226  */
1227 
1228 static u32 fb_get_hfreq(u32 vfreq, u32 yres)
1229 {
1230 	u32 divisor, hfreq;
1231 
1232 	divisor = (1000000 - (vfreq * FLYBACK))/1000;
1233 	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
1234 	return (hfreq/divisor);
1235 }
1236 
1237 static void fb_timings_vfreq(struct __fb_timings *timings)
1238 {
1239 	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
1240 	timings->vblank = fb_get_vblank(timings->hfreq);
1241 	timings->vtotal = timings->vactive + timings->vblank;
1242 	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
1243 						 timings->hactive);
1244 	timings->htotal = timings->hactive + timings->hblank;
1245 	timings->dclk = timings->htotal * timings->hfreq;
1246 }
1247 
1248 static void fb_timings_hfreq(struct __fb_timings *timings)
1249 {
1250 	timings->vblank = fb_get_vblank(timings->hfreq);
1251 	timings->vtotal = timings->vactive + timings->vblank;
1252 	timings->vfreq = timings->hfreq/timings->vtotal;
1253 	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
1254 						 timings->hactive);
1255 	timings->htotal = timings->hactive + timings->hblank;
1256 	timings->dclk = timings->htotal * timings->hfreq;
1257 }
1258 
1259 static void fb_timings_dclk(struct __fb_timings *timings)
1260 {
1261 	timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
1262 						timings->hactive);
1263 	timings->htotal = timings->hactive + timings->hblank;
1264 	timings->hfreq = timings->dclk/timings->htotal;
1265 	timings->vblank = fb_get_vblank(timings->hfreq);
1266 	timings->vtotal = timings->vactive + timings->vblank;
1267 	timings->vfreq = timings->hfreq/timings->vtotal;
1268 }
1269 
1270 /*
1271  * fb_get_mode - calculates video mode using VESA GTF
1272  * @flags: if: 0 - maximize vertical refresh rate
1273  *             1 - vrefresh-driven calculation;
1274  *             2 - hscan-driven calculation;
1275  *             3 - pixelclock-driven calculation;
1276  * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
1277  * @var: pointer to fb_var_screeninfo
1278  * @info: pointer to fb_info
1279  *
1280  * DESCRIPTION:
1281  * Calculates video mode based on monitor specs using VESA GTF.
1282  * The GTF is best for VESA GTF compliant monitors but is
1283  * specifically formulated to work for older monitors as well.
1284  *
1285  * If @flag==0, the function will attempt to maximize the
1286  * refresh rate.  Otherwise, it will calculate timings based on
1287  * the flag and accompanying value.
1288  *
1289  * If FB_IGNOREMON bit is set in @flags, monitor specs will be
1290  * ignored and @var will be filled with the calculated timings.
1291  *
1292  * All calculations are based on the VESA GTF Spreadsheet
1293  * available at VESA's public ftp (http://www.vesa.org).
1294  *
1295  * NOTES:
1296  * The timings generated by the GTF will be different from VESA
1297  * DMT.  It might be a good idea to keep a table of standard
1298  * VESA modes as well.  The GTF may also not work for some displays,
1299  * such as, and especially, analog TV.
1300  *
1301  * REQUIRES:
1302  * A valid info->monspecs, otherwise 'safe numbers' will be used.
1303  */
1304 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
1305 {
1306 	struct __fb_timings *timings;
1307 	u32 interlace = 1, dscan = 1;
1308 	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
1309 
1310 
1311 	timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
1312 
1313 	if (!timings)
1314 		return -ENOMEM;
1315 
1316 	/*
1317 	 * If monspecs are invalid, use values that are enough
1318 	 * for 640x480@60
1319 	 */
1320 	if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
1321 	    !info->monspecs.dclkmax ||
1322 	    info->monspecs.hfmax < info->monspecs.hfmin ||
1323 	    info->monspecs.vfmax < info->monspecs.vfmin ||
1324 	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
1325 		hfmin = 29000; hfmax = 30000;
1326 		vfmin = 60; vfmax = 60;
1327 		dclkmin = 0; dclkmax = 25000000;
1328 	} else {
1329 		hfmin = info->monspecs.hfmin;
1330 		hfmax = info->monspecs.hfmax;
1331 		vfmin = info->monspecs.vfmin;
1332 		vfmax = info->monspecs.vfmax;
1333 		dclkmin = info->monspecs.dclkmin;
1334 		dclkmax = info->monspecs.dclkmax;
1335 	}
1336 
1337 	timings->hactive = var->xres;
1338 	timings->vactive = var->yres;
1339 	if (var->vmode & FB_VMODE_INTERLACED) {
1340 		timings->vactive /= 2;
1341 		interlace = 2;
1342 	}
1343 	if (var->vmode & FB_VMODE_DOUBLE) {
1344 		timings->vactive *= 2;
1345 		dscan = 2;
1346 	}
1347 
1348 	switch (flags & ~FB_IGNOREMON) {
1349 	case FB_MAXTIMINGS: /* maximize refresh rate */
1350 		timings->hfreq = hfmax;
1351 		fb_timings_hfreq(timings);
1352 		if (timings->vfreq > vfmax) {
1353 			timings->vfreq = vfmax;
1354 			fb_timings_vfreq(timings);
1355 		}
1356 		if (timings->dclk > dclkmax) {
1357 			timings->dclk = dclkmax;
1358 			fb_timings_dclk(timings);
1359 		}
1360 		break;
1361 	case FB_VSYNCTIMINGS: /* vrefresh driven */
1362 		timings->vfreq = val;
1363 		fb_timings_vfreq(timings);
1364 		break;
1365 	case FB_HSYNCTIMINGS: /* hsync driven */
1366 		timings->hfreq = val;
1367 		fb_timings_hfreq(timings);
1368 		break;
1369 	case FB_DCLKTIMINGS: /* pixelclock driven */
1370 		timings->dclk = PICOS2KHZ(val) * 1000;
1371 		fb_timings_dclk(timings);
1372 		break;
1373 	default:
1374 		err = -EINVAL;
1375 
1376 	}
1377 
1378 	if (err || (!(flags & FB_IGNOREMON) &&
1379 	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||
1380 	     timings->hfreq < hfmin || timings->hfreq > hfmax ||
1381 	     timings->dclk < dclkmin || timings->dclk > dclkmax))) {
1382 		err = -EINVAL;
1383 	} else {
1384 		var->pixclock = KHZ2PICOS(timings->dclk/1000);
1385 		var->hsync_len = (timings->htotal * 8)/100;
1386 		var->right_margin = (timings->hblank/2) - var->hsync_len;
1387 		var->left_margin = timings->hblank - var->right_margin -
1388 			var->hsync_len;
1389 		var->vsync_len = (3 * interlace)/dscan;
1390 		var->lower_margin = (1 * interlace)/dscan;
1391 		var->upper_margin = (timings->vblank * interlace)/dscan -
1392 			(var->vsync_len + var->lower_margin);
1393 	}
1394 
1395 	kfree(timings);
1396 	return err;
1397 }
1398 
1399 #ifdef CONFIG_VIDEOMODE_HELPERS
1400 int fb_videomode_from_videomode(const struct videomode *vm,
1401 				struct fb_videomode *fbmode)
1402 {
1403 	unsigned int htotal, vtotal;
1404 
1405 	fbmode->xres = vm->hactive;
1406 	fbmode->left_margin = vm->hback_porch;
1407 	fbmode->right_margin = vm->hfront_porch;
1408 	fbmode->hsync_len = vm->hsync_len;
1409 
1410 	fbmode->yres = vm->vactive;
1411 	fbmode->upper_margin = vm->vback_porch;
1412 	fbmode->lower_margin = vm->vfront_porch;
1413 	fbmode->vsync_len = vm->vsync_len;
1414 
1415 	/* prevent division by zero in KHZ2PICOS macro */
1416 	fbmode->pixclock = vm->pixelclock ?
1417 			KHZ2PICOS(vm->pixelclock / 1000) : 0;
1418 
1419 	fbmode->sync = 0;
1420 	fbmode->vmode = 0;
1421 	if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
1422 		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
1423 	if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
1424 		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
1425 	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
1426 		fbmode->vmode |= FB_VMODE_INTERLACED;
1427 	if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
1428 		fbmode->vmode |= FB_VMODE_DOUBLE;
1429 	fbmode->flag = 0;
1430 
1431 	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
1432 		 vm->hsync_len;
1433 	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
1434 		 vm->vsync_len;
1435 	/* prevent division by zero */
1436 	if (htotal && vtotal) {
1437 		fbmode->refresh = vm->pixelclock / (htotal * vtotal);
1438 	/* a mode must have htotal and vtotal != 0 or it is invalid */
1439 	} else {
1440 		fbmode->refresh = 0;
1441 		return -EINVAL;
1442 	}
1443 
1444 	return 0;
1445 }
1446 EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
1447 
1448 #ifdef CONFIG_OF
1449 static inline void dump_fb_videomode(const struct fb_videomode *m)
1450 {
1451 	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
1452 		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
1453 		 m->right_margin, m->upper_margin, m->lower_margin,
1454 		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
1455 }
1456 
1457 /**
1458  * of_get_fb_videomode - get a fb_videomode from devicetree
1459  * @np: device_node with the timing specification
1460  * @fb: will be set to the return value
1461  * @index: index into the list of display timings in devicetree
1462  *
1463  * DESCRIPTION:
1464  * This function is expensive and should only be used, if only one mode is to be
1465  * read from DT. To get multiple modes start with of_get_display_timings ond
1466  * work with that instead.
1467  */
1468 int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
1469 			int index)
1470 {
1471 	struct videomode vm;
1472 	int ret;
1473 
1474 	ret = of_get_videomode(np, &vm, index);
1475 	if (ret)
1476 		return ret;
1477 
1478 	ret = fb_videomode_from_videomode(&vm, fb);
1479 	if (ret)
1480 		return ret;
1481 
1482 	pr_debug("%pOF: got %dx%d display mode from %s\n",
1483 		np, vm.hactive, vm.vactive, np->name);
1484 	dump_fb_videomode(fb);
1485 
1486 	return 0;
1487 }
1488 EXPORT_SYMBOL_GPL(of_get_fb_videomode);
1489 #endif /* CONFIG_OF */
1490 #endif /* CONFIG_VIDEOMODE_HELPERS */
1491 
1492 #else
1493 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
1494 {
1495 	return 1;
1496 }
1497 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1498 {
1499 }
1500 void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1501 {
1502 }
1503 void fb_destroy_modedb(struct fb_videomode *modedb)
1504 {
1505 }
1506 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
1507 		struct fb_info *info)
1508 {
1509 	return -EINVAL;
1510 }
1511 #endif /* CONFIG_FB_MODE_HELPERS */
1512 
1513 /*
1514  * fb_validate_mode - validates var against monitor capabilities
1515  * @var: pointer to fb_var_screeninfo
1516  * @info: pointer to fb_info
1517  *
1518  * DESCRIPTION:
1519  * Validates video mode against monitor capabilities specified in
1520  * info->monspecs.
1521  *
1522  * REQUIRES:
1523  * A valid info->monspecs.
1524  */
1525 int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
1526 {
1527 	u32 hfreq, vfreq, htotal, vtotal, pixclock;
1528 	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
1529 
1530 	/*
1531 	 * If monspecs are invalid, use values that are enough
1532 	 * for 640x480@60
1533 	 */
1534 	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
1535 	    !info->monspecs.dclkmax ||
1536 	    info->monspecs.hfmax < info->monspecs.hfmin ||
1537 	    info->monspecs.vfmax < info->monspecs.vfmin ||
1538 	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
1539 		hfmin = 29000; hfmax = 30000;
1540 		vfmin = 60; vfmax = 60;
1541 		dclkmin = 0; dclkmax = 25000000;
1542 	} else {
1543 		hfmin = info->monspecs.hfmin;
1544 		hfmax = info->monspecs.hfmax;
1545 		vfmin = info->monspecs.vfmin;
1546 		vfmax = info->monspecs.vfmax;
1547 		dclkmin = info->monspecs.dclkmin;
1548 		dclkmax = info->monspecs.dclkmax;
1549 	}
1550 
1551 	if (!var->pixclock)
1552 		return -EINVAL;
1553 	pixclock = PICOS2KHZ(var->pixclock) * 1000;
1554 
1555 	htotal = var->xres + var->right_margin + var->hsync_len +
1556 		var->left_margin;
1557 	vtotal = var->yres + var->lower_margin + var->vsync_len +
1558 		var->upper_margin;
1559 
1560 	if (var->vmode & FB_VMODE_INTERLACED)
1561 		vtotal /= 2;
1562 	if (var->vmode & FB_VMODE_DOUBLE)
1563 		vtotal *= 2;
1564 
1565 	hfreq = pixclock/htotal;
1566 	hfreq = (hfreq + 500) / 1000 * 1000;
1567 
1568 	vfreq = hfreq/vtotal;
1569 
1570 	return (vfreq < vfmin || vfreq > vfmax ||
1571 		hfreq < hfmin || hfreq > hfmax ||
1572 		pixclock < dclkmin || pixclock > dclkmax) ?
1573 		-EINVAL : 0;
1574 }
1575 
1576 #if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
1577 
1578 /*
1579  * We need to ensure that the EDID block is only returned for
1580  * the primary graphics adapter.
1581  */
1582 
1583 const unsigned char *fb_firmware_edid(struct device *device)
1584 {
1585 	struct pci_dev *dev = NULL;
1586 	struct resource *res = NULL;
1587 	unsigned char *edid = NULL;
1588 
1589 	if (device)
1590 		dev = to_pci_dev(device);
1591 
1592 	if (dev)
1593 		res = &dev->resource[PCI_ROM_RESOURCE];
1594 
1595 	if (res && res->flags & IORESOURCE_ROM_SHADOW)
1596 		edid = edid_info.dummy;
1597 
1598 	return edid;
1599 }
1600 #else
1601 const unsigned char *fb_firmware_edid(struct device *device)
1602 {
1603 	return NULL;
1604 }
1605 #endif
1606 EXPORT_SYMBOL(fb_firmware_edid);
1607 
1608 EXPORT_SYMBOL(fb_parse_edid);
1609 EXPORT_SYMBOL(fb_edid_to_monspecs);
1610 EXPORT_SYMBOL(fb_edid_add_monspecs);
1611 EXPORT_SYMBOL(fb_get_mode);
1612 EXPORT_SYMBOL(fb_validate_mode);
1613 EXPORT_SYMBOL(fb_destroy_modedb);
1614