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