xref: /openbmc/linux/drivers/video/fbdev/core/fbmon.c (revision d003d772)
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 = kcalloc(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_array(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 	if (!specs->modedb)
982 		return;
983 
984 	/*
985 	 * Workaround for buggy EDIDs that sets that the first
986 	 * detailed timing is preferred but has not detailed
987 	 * timing specified
988 	 */
989 	for (i = 0; i < specs->modedb_len; i++) {
990 		if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
991 			found = 1;
992 			break;
993 		}
994 	}
995 
996 	if (!found)
997 		specs->misc &= ~FB_MISC_1ST_DETAIL;
998 
999 	DPRINTK("========================================\n");
1000 }
1001 
1002 /**
1003  * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
1004  * @edid:	128 byte array with an E-EDID block
1005  * @spacs:	monitor specs to be extended
1006  */
1007 void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1008 {
1009 	unsigned char *block;
1010 	struct fb_videomode *m;
1011 	int num = 0, i;
1012 	u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
1013 	u8 pos = 4, svd_n = 0;
1014 
1015 	if (!edid)
1016 		return;
1017 
1018 	if (!edid_checksum(edid))
1019 		return;
1020 
1021 	if (edid[0] != 0x2 ||
1022 	    edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
1023 		return;
1024 
1025 	DPRINTK("  Short Video Descriptors\n");
1026 
1027 	while (pos < edid[2]) {
1028 		u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
1029 		pr_debug("Data block %u of %u bytes\n", type, len);
1030 		if (type == 2) {
1031 			for (i = pos; i < pos + len; i++) {
1032 				u8 idx = edid[pos + i] & 0x7f;
1033 				svd[svd_n++] = idx;
1034 				pr_debug("N%sative mode #%d\n",
1035 					 edid[pos + i] & 0x80 ? "" : "on-n", idx);
1036 			}
1037 		} else if (type == 3 && len >= 3) {
1038 			/* Check Vendor Specific Data Block.  For HDMI,
1039 			   it is always 00-0C-03 for HDMI Licensing, LLC. */
1040 			if (edid[pos + 1] == 3 && edid[pos + 2] == 0xc &&
1041 			    edid[pos + 3] == 0)
1042 				specs->misc |= FB_MISC_HDMI;
1043 		}
1044 		pos += len + 1;
1045 	}
1046 
1047 	block = edid + edid[2];
1048 
1049 	DPRINTK("  Extended Detailed Timings\n");
1050 
1051 	for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
1052 	     i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
1053 		if (PIXEL_CLOCK != 0)
1054 			edt[num++] = block - edid;
1055 
1056 	/* Yikes, EDID data is totally useless */
1057 	if (!(num + svd_n))
1058 		return;
1059 
1060 	m = kcalloc(specs->modedb_len + num + svd_n,
1061 		    sizeof(struct fb_videomode),
1062 		    GFP_KERNEL);
1063 
1064 	if (!m)
1065 		return;
1066 
1067 	memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
1068 
1069 	for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
1070 		get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
1071 		if (i == specs->modedb_len)
1072 			m[i].flag |= FB_MODE_IS_FIRST;
1073 		pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
1074 	}
1075 
1076 	for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
1077 		int idx = svd[i - specs->modedb_len - num];
1078 		if (!idx || idx >= ARRAY_SIZE(cea_modes)) {
1079 			pr_warn("Reserved SVD code %d\n", idx);
1080 		} else if (!cea_modes[idx].xres) {
1081 			pr_warn("Unimplemented SVD code %d\n", idx);
1082 		} else {
1083 			memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
1084 			pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
1085 				 m[i].xres, m[i].yres, m[i].refresh);
1086 		}
1087 	}
1088 
1089 	kfree(specs->modedb);
1090 	specs->modedb = m;
1091 	specs->modedb_len = specs->modedb_len + num + svd_n;
1092 }
1093 
1094 /*
1095  * VESA Generalized Timing Formula (GTF)
1096  */
1097 
1098 #define FLYBACK                     550
1099 #define V_FRONTPORCH                1
1100 #define H_OFFSET                    40
1101 #define H_SCALEFACTOR               20
1102 #define H_BLANKSCALE                128
1103 #define H_GRADIENT                  600
1104 #define C_VAL                       30
1105 #define M_VAL                       300
1106 
1107 struct __fb_timings {
1108 	u32 dclk;
1109 	u32 hfreq;
1110 	u32 vfreq;
1111 	u32 hactive;
1112 	u32 vactive;
1113 	u32 hblank;
1114 	u32 vblank;
1115 	u32 htotal;
1116 	u32 vtotal;
1117 };
1118 
1119 /**
1120  * fb_get_vblank - get vertical blank time
1121  * @hfreq: horizontal freq
1122  *
1123  * DESCRIPTION:
1124  * vblank = right_margin + vsync_len + left_margin
1125  *
1126  *    given: right_margin = 1 (V_FRONTPORCH)
1127  *           vsync_len    = 3
1128  *           flyback      = 550
1129  *
1130  *                          flyback * hfreq
1131  *           left_margin  = --------------- - vsync_len
1132  *                           1000000
1133  */
1134 static u32 fb_get_vblank(u32 hfreq)
1135 {
1136 	u32 vblank;
1137 
1138 	vblank = (hfreq * FLYBACK)/1000;
1139 	vblank = (vblank + 500)/1000;
1140 	return (vblank + V_FRONTPORCH);
1141 }
1142 
1143 /**
1144  * fb_get_hblank_by_freq - get horizontal blank time given hfreq
1145  * @hfreq: horizontal freq
1146  * @xres: horizontal resolution in pixels
1147  *
1148  * DESCRIPTION:
1149  *
1150  *           xres * duty_cycle
1151  * hblank = ------------------
1152  *           100 - duty_cycle
1153  *
1154  * duty cycle = percent of htotal assigned to inactive display
1155  * duty cycle = C - (M/Hfreq)
1156  *
1157  * where: C = ((offset - scale factor) * blank_scale)
1158  *            -------------------------------------- + scale factor
1159  *                        256
1160  *        M = blank_scale * gradient
1161  *
1162  */
1163 static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
1164 {
1165 	u32 c_val, m_val, duty_cycle, hblank;
1166 
1167 	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
1168 		 H_SCALEFACTOR) * 1000;
1169 	m_val = (H_BLANKSCALE * H_GRADIENT)/256;
1170 	m_val = (m_val * 1000000)/hfreq;
1171 	duty_cycle = c_val - m_val;
1172 	hblank = (xres * duty_cycle)/(100000 - duty_cycle);
1173 	return (hblank);
1174 }
1175 
1176 /**
1177  * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
1178  * @dclk: pixelclock in Hz
1179  * @xres: horizontal resolution in pixels
1180  *
1181  * DESCRIPTION:
1182  *
1183  *           xres * duty_cycle
1184  * hblank = ------------------
1185  *           100 - duty_cycle
1186  *
1187  * duty cycle = percent of htotal assigned to inactive display
1188  * duty cycle = C - (M * h_period)
1189  *
1190  * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
1191  *                   -----------------------------------------------
1192  *                                    2 * M
1193  *        M = 300;
1194  *        C = 30;
1195 
1196  */
1197 static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
1198 {
1199 	u32 duty_cycle, h_period, hblank;
1200 
1201 	dclk /= 1000;
1202 	h_period = 100 - C_VAL;
1203 	h_period *= h_period;
1204 	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
1205 	h_period *= 10000;
1206 
1207 	h_period = int_sqrt(h_period);
1208 	h_period -= (100 - C_VAL) * 100;
1209 	h_period *= 1000;
1210 	h_period /= 2 * M_VAL;
1211 
1212 	duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
1213 	hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
1214 	hblank &= ~15;
1215 	return (hblank);
1216 }
1217 
1218 /**
1219  * fb_get_hfreq - estimate hsync
1220  * @vfreq: vertical refresh rate
1221  * @yres: vertical resolution
1222  *
1223  * DESCRIPTION:
1224  *
1225  *          (yres + front_port) * vfreq * 1000000
1226  * hfreq = -------------------------------------
1227  *          (1000000 - (vfreq * FLYBACK)
1228  *
1229  */
1230 
1231 static u32 fb_get_hfreq(u32 vfreq, u32 yres)
1232 {
1233 	u32 divisor, hfreq;
1234 
1235 	divisor = (1000000 - (vfreq * FLYBACK))/1000;
1236 	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
1237 	return (hfreq/divisor);
1238 }
1239 
1240 static void fb_timings_vfreq(struct __fb_timings *timings)
1241 {
1242 	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
1243 	timings->vblank = fb_get_vblank(timings->hfreq);
1244 	timings->vtotal = timings->vactive + timings->vblank;
1245 	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
1246 						 timings->hactive);
1247 	timings->htotal = timings->hactive + timings->hblank;
1248 	timings->dclk = timings->htotal * timings->hfreq;
1249 }
1250 
1251 static void fb_timings_hfreq(struct __fb_timings *timings)
1252 {
1253 	timings->vblank = fb_get_vblank(timings->hfreq);
1254 	timings->vtotal = timings->vactive + timings->vblank;
1255 	timings->vfreq = timings->hfreq/timings->vtotal;
1256 	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
1257 						 timings->hactive);
1258 	timings->htotal = timings->hactive + timings->hblank;
1259 	timings->dclk = timings->htotal * timings->hfreq;
1260 }
1261 
1262 static void fb_timings_dclk(struct __fb_timings *timings)
1263 {
1264 	timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
1265 						timings->hactive);
1266 	timings->htotal = timings->hactive + timings->hblank;
1267 	timings->hfreq = timings->dclk/timings->htotal;
1268 	timings->vblank = fb_get_vblank(timings->hfreq);
1269 	timings->vtotal = timings->vactive + timings->vblank;
1270 	timings->vfreq = timings->hfreq/timings->vtotal;
1271 }
1272 
1273 /*
1274  * fb_get_mode - calculates video mode using VESA GTF
1275  * @flags: if: 0 - maximize vertical refresh rate
1276  *             1 - vrefresh-driven calculation;
1277  *             2 - hscan-driven calculation;
1278  *             3 - pixelclock-driven calculation;
1279  * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
1280  * @var: pointer to fb_var_screeninfo
1281  * @info: pointer to fb_info
1282  *
1283  * DESCRIPTION:
1284  * Calculates video mode based on monitor specs using VESA GTF.
1285  * The GTF is best for VESA GTF compliant monitors but is
1286  * specifically formulated to work for older monitors as well.
1287  *
1288  * If @flag==0, the function will attempt to maximize the
1289  * refresh rate.  Otherwise, it will calculate timings based on
1290  * the flag and accompanying value.
1291  *
1292  * If FB_IGNOREMON bit is set in @flags, monitor specs will be
1293  * ignored and @var will be filled with the calculated timings.
1294  *
1295  * All calculations are based on the VESA GTF Spreadsheet
1296  * available at VESA's public ftp (http://www.vesa.org).
1297  *
1298  * NOTES:
1299  * The timings generated by the GTF will be different from VESA
1300  * DMT.  It might be a good idea to keep a table of standard
1301  * VESA modes as well.  The GTF may also not work for some displays,
1302  * such as, and especially, analog TV.
1303  *
1304  * REQUIRES:
1305  * A valid info->monspecs, otherwise 'safe numbers' will be used.
1306  */
1307 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
1308 {
1309 	struct __fb_timings *timings;
1310 	u32 interlace = 1, dscan = 1;
1311 	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
1312 
1313 
1314 	timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
1315 
1316 	if (!timings)
1317 		return -ENOMEM;
1318 
1319 	/*
1320 	 * If monspecs are invalid, use values that are enough
1321 	 * for 640x480@60
1322 	 */
1323 	if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
1324 	    !info->monspecs.dclkmax ||
1325 	    info->monspecs.hfmax < info->monspecs.hfmin ||
1326 	    info->monspecs.vfmax < info->monspecs.vfmin ||
1327 	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
1328 		hfmin = 29000; hfmax = 30000;
1329 		vfmin = 60; vfmax = 60;
1330 		dclkmin = 0; dclkmax = 25000000;
1331 	} else {
1332 		hfmin = info->monspecs.hfmin;
1333 		hfmax = info->monspecs.hfmax;
1334 		vfmin = info->monspecs.vfmin;
1335 		vfmax = info->monspecs.vfmax;
1336 		dclkmin = info->monspecs.dclkmin;
1337 		dclkmax = info->monspecs.dclkmax;
1338 	}
1339 
1340 	timings->hactive = var->xres;
1341 	timings->vactive = var->yres;
1342 	if (var->vmode & FB_VMODE_INTERLACED) {
1343 		timings->vactive /= 2;
1344 		interlace = 2;
1345 	}
1346 	if (var->vmode & FB_VMODE_DOUBLE) {
1347 		timings->vactive *= 2;
1348 		dscan = 2;
1349 	}
1350 
1351 	switch (flags & ~FB_IGNOREMON) {
1352 	case FB_MAXTIMINGS: /* maximize refresh rate */
1353 		timings->hfreq = hfmax;
1354 		fb_timings_hfreq(timings);
1355 		if (timings->vfreq > vfmax) {
1356 			timings->vfreq = vfmax;
1357 			fb_timings_vfreq(timings);
1358 		}
1359 		if (timings->dclk > dclkmax) {
1360 			timings->dclk = dclkmax;
1361 			fb_timings_dclk(timings);
1362 		}
1363 		break;
1364 	case FB_VSYNCTIMINGS: /* vrefresh driven */
1365 		timings->vfreq = val;
1366 		fb_timings_vfreq(timings);
1367 		break;
1368 	case FB_HSYNCTIMINGS: /* hsync driven */
1369 		timings->hfreq = val;
1370 		fb_timings_hfreq(timings);
1371 		break;
1372 	case FB_DCLKTIMINGS: /* pixelclock driven */
1373 		timings->dclk = PICOS2KHZ(val) * 1000;
1374 		fb_timings_dclk(timings);
1375 		break;
1376 	default:
1377 		err = -EINVAL;
1378 
1379 	}
1380 
1381 	if (err || (!(flags & FB_IGNOREMON) &&
1382 	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||
1383 	     timings->hfreq < hfmin || timings->hfreq > hfmax ||
1384 	     timings->dclk < dclkmin || timings->dclk > dclkmax))) {
1385 		err = -EINVAL;
1386 	} else {
1387 		var->pixclock = KHZ2PICOS(timings->dclk/1000);
1388 		var->hsync_len = (timings->htotal * 8)/100;
1389 		var->right_margin = (timings->hblank/2) - var->hsync_len;
1390 		var->left_margin = timings->hblank - var->right_margin -
1391 			var->hsync_len;
1392 		var->vsync_len = (3 * interlace)/dscan;
1393 		var->lower_margin = (1 * interlace)/dscan;
1394 		var->upper_margin = (timings->vblank * interlace)/dscan -
1395 			(var->vsync_len + var->lower_margin);
1396 	}
1397 
1398 	kfree(timings);
1399 	return err;
1400 }
1401 
1402 #ifdef CONFIG_VIDEOMODE_HELPERS
1403 int fb_videomode_from_videomode(const struct videomode *vm,
1404 				struct fb_videomode *fbmode)
1405 {
1406 	unsigned int htotal, vtotal;
1407 
1408 	fbmode->xres = vm->hactive;
1409 	fbmode->left_margin = vm->hback_porch;
1410 	fbmode->right_margin = vm->hfront_porch;
1411 	fbmode->hsync_len = vm->hsync_len;
1412 
1413 	fbmode->yres = vm->vactive;
1414 	fbmode->upper_margin = vm->vback_porch;
1415 	fbmode->lower_margin = vm->vfront_porch;
1416 	fbmode->vsync_len = vm->vsync_len;
1417 
1418 	/* prevent division by zero in KHZ2PICOS macro */
1419 	fbmode->pixclock = vm->pixelclock ?
1420 			KHZ2PICOS(vm->pixelclock / 1000) : 0;
1421 
1422 	fbmode->sync = 0;
1423 	fbmode->vmode = 0;
1424 	if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
1425 		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
1426 	if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
1427 		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
1428 	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
1429 		fbmode->vmode |= FB_VMODE_INTERLACED;
1430 	if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
1431 		fbmode->vmode |= FB_VMODE_DOUBLE;
1432 	fbmode->flag = 0;
1433 
1434 	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
1435 		 vm->hsync_len;
1436 	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
1437 		 vm->vsync_len;
1438 	/* prevent division by zero */
1439 	if (htotal && vtotal) {
1440 		fbmode->refresh = vm->pixelclock / (htotal * vtotal);
1441 	/* a mode must have htotal and vtotal != 0 or it is invalid */
1442 	} else {
1443 		fbmode->refresh = 0;
1444 		return -EINVAL;
1445 	}
1446 
1447 	return 0;
1448 }
1449 EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
1450 
1451 #ifdef CONFIG_OF
1452 static inline void dump_fb_videomode(const struct fb_videomode *m)
1453 {
1454 	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
1455 		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
1456 		 m->right_margin, m->upper_margin, m->lower_margin,
1457 		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
1458 }
1459 
1460 /**
1461  * of_get_fb_videomode - get a fb_videomode from devicetree
1462  * @np: device_node with the timing specification
1463  * @fb: will be set to the return value
1464  * @index: index into the list of display timings in devicetree
1465  *
1466  * DESCRIPTION:
1467  * This function is expensive and should only be used, if only one mode is to be
1468  * read from DT. To get multiple modes start with of_get_display_timings ond
1469  * work with that instead.
1470  */
1471 int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
1472 			int index)
1473 {
1474 	struct videomode vm;
1475 	int ret;
1476 
1477 	ret = of_get_videomode(np, &vm, index);
1478 	if (ret)
1479 		return ret;
1480 
1481 	ret = fb_videomode_from_videomode(&vm, fb);
1482 	if (ret)
1483 		return ret;
1484 
1485 	pr_debug("%pOF: got %dx%d display mode\n",
1486 		np, vm.hactive, vm.vactive);
1487 	dump_fb_videomode(fb);
1488 
1489 	return 0;
1490 }
1491 EXPORT_SYMBOL_GPL(of_get_fb_videomode);
1492 #endif /* CONFIG_OF */
1493 #endif /* CONFIG_VIDEOMODE_HELPERS */
1494 
1495 #else
1496 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
1497 {
1498 	return 1;
1499 }
1500 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1501 {
1502 }
1503 void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1504 {
1505 }
1506 void fb_destroy_modedb(struct fb_videomode *modedb)
1507 {
1508 }
1509 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
1510 		struct fb_info *info)
1511 {
1512 	return -EINVAL;
1513 }
1514 #endif /* CONFIG_FB_MODE_HELPERS */
1515 
1516 /*
1517  * fb_validate_mode - validates var against monitor capabilities
1518  * @var: pointer to fb_var_screeninfo
1519  * @info: pointer to fb_info
1520  *
1521  * DESCRIPTION:
1522  * Validates video mode against monitor capabilities specified in
1523  * info->monspecs.
1524  *
1525  * REQUIRES:
1526  * A valid info->monspecs.
1527  */
1528 int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
1529 {
1530 	u32 hfreq, vfreq, htotal, vtotal, pixclock;
1531 	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
1532 
1533 	/*
1534 	 * If monspecs are invalid, use values that are enough
1535 	 * for 640x480@60
1536 	 */
1537 	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
1538 	    !info->monspecs.dclkmax ||
1539 	    info->monspecs.hfmax < info->monspecs.hfmin ||
1540 	    info->monspecs.vfmax < info->monspecs.vfmin ||
1541 	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
1542 		hfmin = 29000; hfmax = 30000;
1543 		vfmin = 60; vfmax = 60;
1544 		dclkmin = 0; dclkmax = 25000000;
1545 	} else {
1546 		hfmin = info->monspecs.hfmin;
1547 		hfmax = info->monspecs.hfmax;
1548 		vfmin = info->monspecs.vfmin;
1549 		vfmax = info->monspecs.vfmax;
1550 		dclkmin = info->monspecs.dclkmin;
1551 		dclkmax = info->monspecs.dclkmax;
1552 	}
1553 
1554 	if (!var->pixclock)
1555 		return -EINVAL;
1556 	pixclock = PICOS2KHZ(var->pixclock) * 1000;
1557 
1558 	htotal = var->xres + var->right_margin + var->hsync_len +
1559 		var->left_margin;
1560 	vtotal = var->yres + var->lower_margin + var->vsync_len +
1561 		var->upper_margin;
1562 
1563 	if (var->vmode & FB_VMODE_INTERLACED)
1564 		vtotal /= 2;
1565 	if (var->vmode & FB_VMODE_DOUBLE)
1566 		vtotal *= 2;
1567 
1568 	hfreq = pixclock/htotal;
1569 	hfreq = (hfreq + 500) / 1000 * 1000;
1570 
1571 	vfreq = hfreq/vtotal;
1572 
1573 	return (vfreq < vfmin || vfreq > vfmax ||
1574 		hfreq < hfmin || hfreq > hfmax ||
1575 		pixclock < dclkmin || pixclock > dclkmax) ?
1576 		-EINVAL : 0;
1577 }
1578 
1579 #if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
1580 
1581 /*
1582  * We need to ensure that the EDID block is only returned for
1583  * the primary graphics adapter.
1584  */
1585 
1586 const unsigned char *fb_firmware_edid(struct device *device)
1587 {
1588 	struct pci_dev *dev = NULL;
1589 	struct resource *res = NULL;
1590 	unsigned char *edid = NULL;
1591 
1592 	if (device)
1593 		dev = to_pci_dev(device);
1594 
1595 	if (dev)
1596 		res = &dev->resource[PCI_ROM_RESOURCE];
1597 
1598 	if (res && res->flags & IORESOURCE_ROM_SHADOW)
1599 		edid = edid_info.dummy;
1600 
1601 	return edid;
1602 }
1603 #else
1604 const unsigned char *fb_firmware_edid(struct device *device)
1605 {
1606 	return NULL;
1607 }
1608 #endif
1609 EXPORT_SYMBOL(fb_firmware_edid);
1610 
1611 EXPORT_SYMBOL(fb_parse_edid);
1612 EXPORT_SYMBOL(fb_edid_to_monspecs);
1613 EXPORT_SYMBOL(fb_edid_add_monspecs);
1614 EXPORT_SYMBOL(fb_get_mode);
1615 EXPORT_SYMBOL(fb_validate_mode);
1616 EXPORT_SYMBOL(fb_destroy_modedb);
1617