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