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