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