Coarsly sort out 32-bit-only, 64-bit-only and ``portable'' MIPS lib/
[linux-2.6/linux-mips.git] / drivers / video / fbmon.c
blob59533c4897febf6adc41fc7854584852faba0958
1 /*
2 * linux/drivers/video/fbmon.c
4 * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
6 * Credits:
7 *
8 * The EDID Parser is a conglomeration from the following sources:
10 * 1. SciTech SNAP Graphics Architecture
11 * Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
13 * 2. XFree86 4.3.0, interpret_edid.c
14 * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
16 * 3. John Fremlin <vii@users.sourceforge.net> and
17 * Ani Joshi <ajoshi@unixbox.com>
19 * Generalized Timing Formula is derived from:
21 * GTF Spreadsheet by Andy Morrish (1/5/97)
22 * available at http://www.vesa.org
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.
29 #include <linux/tty.h>
30 #include <linux/fb.h>
31 #include <linux/module.h>
32 #ifdef CONFIG_PPC_OF
33 #include <linux/pci.h>
34 #include <asm/prom.h>
35 #endif
36 #include <video/edid.h>
37 #include "edid.h"
39 /*
40 * EDID parser
43 const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
44 0xff, 0xff, 0xff, 0x00
46 const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
48 static void copy_string(unsigned char *c, unsigned char *s)
50 int i;
51 c = c + 5;
52 for (i = 0; (i < 13 && *c != 0x0A); i++)
53 *(s++) = *(c++);
54 *s = 0;
55 while (i-- && (*--s == 0x20)) *s = 0;
58 static int edid_checksum(unsigned char *edid)
60 unsigned char i, csum = 0;
62 for (i = 0; i < EDID_LENGTH; i++)
63 csum += edid[i];
65 if (csum == 0x00) {
66 /* checksum passed, everything's good */
67 return 1;
68 } else {
69 printk("EDID checksum failed, aborting\n");
70 return 0;
74 static int edid_check_header(unsigned char *edid)
76 if ((edid[0] != 0x00) || (edid[1] != 0xff) || (edid[2] != 0xff) ||
77 (edid[3] != 0xff) || (edid[4] != 0xff) || (edid[5] != 0xff) ||
78 (edid[6] != 0xff)) {
79 printk
80 ("EDID header doesn't match EDID v1 header, aborting\n");
81 return 0;
83 return 1;
86 static void parse_vendor_block(unsigned char *block)
88 unsigned char c[4];
90 c[0] = ((block[0] & 0x7c) >> 2) + '@';
91 c[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@';
92 c[2] = (block[1] & 0x1f) + '@';
93 c[3] = 0;
94 printk(" Manufacturer: %s ", c);
95 printk("Model: %x ", block[2] + (block[3] << 8));
96 printk("Serial#: %u\n", block[4] + (block[5] << 8) +
97 (block[6] << 16) + (block[7] << 24));
98 printk(" Year: %u Week %u\n", block[9] + 1990, block[8]);
101 static void parse_dpms_capabilities(unsigned char flags)
103 printk(" DPMS: Active %s, Suspend %s, Standby %s\n",
104 (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
105 (flags & DPMS_SUSPEND) ? "yes" : "no",
106 (flags & DPMS_STANDBY) ? "yes" : "no");
109 static void print_chroma(unsigned char *block)
111 int tmp;
113 /* Chromaticity data */
114 printk(" Chromaticity: ");
115 tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
116 tmp *= 1000;
117 tmp += 512;
118 printk("RedX: 0.%03d ", tmp/1024);
120 tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
121 tmp *= 1000;
122 tmp += 512;
123 printk("RedY: 0.%03d\n", tmp/1024);
125 tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
126 tmp *= 1000;
127 tmp += 512;
128 printk(" GreenX: 0.%03d ", tmp/1024);
130 tmp = (block[5] & 3) | (block[0xa] << 2);
131 tmp *= 1000;
132 tmp += 512;
133 printk("GreenY: 0.%03d\n", tmp/1024);
135 tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
136 tmp *= 1000;
137 tmp += 512;
138 printk(" BlueX: 0.%03d ", tmp/1024);
140 tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
141 tmp *= 1000;
142 tmp += 512;
143 printk("BlueY: 0.%03d\n", tmp/1024);
145 tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
146 tmp *= 1000;
147 tmp += 512;
148 printk(" WhiteX: 0.%03d ", tmp/1024);
150 tmp = (block[6] & 3) | (block[0xe] << 2);
151 tmp *= 1000;
152 tmp += 512;
153 printk("WhiteY: 0.%03d\n", tmp/1024);
156 static void parse_display_block(unsigned char *block)
158 unsigned char c;
160 c = (block[0] & 0x80) >> 7;
161 if (c)
162 printk(" Digital Display Input");
163 else {
164 printk(" Analog Display Input: Input Voltage - ");
165 switch ((block[0] & 0x60) >> 5) {
166 case 0:
167 printk("0.700V/0.300V");
168 break;
169 case 1:
170 printk("0.714V/0.286V");
171 break;
172 case 2:
173 printk("1.000V/0.400V");
174 break;
175 case 3:
176 printk("0.700V/0.000V");
177 break;
178 default:
179 printk("unknown");
181 printk("\n");
183 c = (block[0] & 0x10) >> 4;
184 if (c)
185 printk(" Configurable signal level\n");
186 printk(" Sync: ");
187 c = block[0] & 0x0f;
188 if (c & 0x10)
189 printk("Blank to Blank ");
190 if (c & 0x08)
191 printk("Separate ");
192 if (c & 0x04)
193 printk("Composite ");
194 if (c & 0x02)
195 printk("Sync on Green ");
196 if (c & 0x01)
197 printk("Serration on ");
198 printk("\n");
200 printk(" Max H-size in cm: ");
201 c = block[1];
202 if (c)
203 printk("%d\n", c);
204 else
205 printk("variable\n");
207 printk(" Max V-size in cm: ");
208 c = block[2];
209 if (c)
210 printk("%d\n", c);
211 else
212 printk("variable\n");
214 c = block[3];
215 printk(" Gamma: ");
216 printk("%d.%d\n", (c + 100)/100, (c+100) % 100);
218 parse_dpms_capabilities(block[4]);
220 switch ((block[4] & 0x18) >> 3) {
221 case 0:
222 printk(" Monochrome/Grayscale\n");
223 break;
224 case 1:
225 printk(" RGB Color Display\n");
226 break;
227 case 2:
228 printk(" Non-RGB Multicolor Display\n");
229 break;
230 default:
231 printk(" Unknown\n");
232 break;
235 print_chroma(block);
237 c = block[4] & 0x7;
238 if (c & 0x04)
239 printk(" Default color format is primary\n");
240 if (c & 0x02)
241 printk(" First DETAILED Timing is preferred\n");
242 if (c & 0x01)
243 printk(" Display is GTF capable\n");
246 static void parse_std_md_block(unsigned char *block)
248 unsigned char c;
250 c = block[0];
251 if (c&0x80) printk(" 720x400@70Hz\n");
252 if (c&0x40) printk(" 720x400@88Hz\n");
253 if (c&0x20) printk(" 640x480@60Hz\n");
254 if (c&0x10) printk(" 640x480@67Hz\n");
255 if (c&0x08) printk(" 640x480@72Hz\n");
256 if (c&0x04) printk(" 640x480@75Hz\n");
257 if (c&0x02) printk(" 800x600@56Hz\n");
258 if (c&0x01) printk(" 800x600@60Hz\n");
260 c = block[1];
261 if (c&0x80) printk(" 800x600@72Hz\n");
262 if (c&0x40) printk(" 800x600@75Hz\n");
263 if (c&0x20) printk(" 832x624@75Hz\n");
264 if (c&0x10) printk(" 1024x768@87Hz (interlaced)\n");
265 if (c&0x08) printk(" 1024x768@60Hz\n");
266 if (c&0x04) printk(" 1024x768@70Hz\n");
267 if (c&0x02) printk(" 1024x768@75Hz\n");
268 if (c&0x01) printk(" 1280x1024@75Hz\n");
270 c = block[2];
271 if (c&0x80) printk(" 1152x870@75Hz\n");
272 printk(" Manufacturer's mask: %x\n",c&0x7F);
276 static int edid_is_timing_block(unsigned char *block)
278 if ((block[0] != 0x00) || (block[1] != 0x00) ||
279 (block[2] != 0x00) || (block[4] != 0x00))
280 return 1;
281 else
282 return 0;
285 static int edid_is_serial_block(unsigned char *block)
287 if ((block[0] == 0x00) && (block[1] == 0x00) &&
288 (block[2] == 0x00) && (block[3] == 0xff) &&
289 (block[4] == 0x00))
290 return 1;
291 else
292 return 0;
295 static int edid_is_ascii_block(unsigned char *block)
297 if ((block[0] == 0x00) && (block[1] == 0x00) &&
298 (block[2] == 0x00) && (block[3] == 0xfe) &&
299 (block[4] == 0x00))
300 return 1;
301 else
302 return 0;
305 static int edid_is_limits_block(unsigned char *block)
307 if ((block[0] == 0x00) && (block[1] == 0x00) &&
308 (block[2] == 0x00) && (block[3] == 0xfd) &&
309 (block[4] == 0x00))
310 return 1;
311 else
312 return 0;
315 static int edid_is_monitor_block(unsigned char *block)
317 if ((block[0] == 0x00) && (block[1] == 0x00) &&
318 (block[2] == 0x00) && (block[3] == 0xfc) &&
319 (block[4] == 0x00))
320 return 1;
321 else
322 return 0;
325 static int edid_is_color_block(unsigned char *block)
327 if ((block[0] == 0x00) && (block[1] == 0x00) &&
328 (block[2] == 0x00) && (block[3] == 0xfb) &&
329 (block[4] == 0x00))
330 return 1;
331 else
332 return 0;
335 static int edid_is_std_timings_block(unsigned char *block)
337 if ((block[0] == 0x00) && (block[1] == 0x00) &&
338 (block[2] == 0x00) && (block[3] == 0xfa) &&
339 (block[4] == 0x00))
340 return 1;
341 else
342 return 0;
345 static void parse_serial_block(unsigned char *block)
347 unsigned char c[13];
349 copy_string(block, c);
350 printk(" Serial No : %s\n", c);
353 static void parse_ascii_block(unsigned char *block)
355 unsigned char c[13];
357 copy_string(block, c);
358 printk(" %s\n", c);
361 static void parse_limits_block(unsigned char *block)
363 printk(" HorizSync : %d-%d KHz\n", H_MIN_RATE, H_MAX_RATE);
364 printk(" VertRefresh : %d-%d Hz\n", V_MIN_RATE, V_MAX_RATE);
365 if (MAX_PIXEL_CLOCK != 10*0xff)
366 printk(" Max Pixelclock: %d MHz\n", (int) MAX_PIXEL_CLOCK);
369 static void parse_monitor_block(unsigned char *block)
371 unsigned char c[13];
373 copy_string(block, c);
374 printk(" Monitor Name : %s\n", c);
377 static void parse_color_block(unsigned char *block)
379 printk(" Color Point : unimplemented\n");
382 static void parse_std_timing_block(unsigned char *block)
384 int xres, yres = 0, refresh, ratio, err = 1;
386 xres = (block[0] + 31) * 8;
387 if (xres <= 256)
388 return;
390 ratio = (block[1] & 0xc0) >> 6;
391 switch (ratio) {
392 case 0:
393 yres = xres;
394 break;
395 case 1:
396 yres = (xres * 3)/4;
397 break;
398 case 2:
399 yres = (xres * 4)/5;
400 break;
401 case 3:
402 yres = (xres * 9)/16;
403 break;
405 refresh = (block[1] & 0x3f) + 60;
406 printk(" %dx%d@%dHz\n", xres, yres, refresh);
407 err = 0;
410 static void parse_dst_timing_block(unsigned char *block)
412 int i;
414 block += 5;
415 for (i = 0; i < 5; i++, block += STD_TIMING_DESCRIPTION_SIZE)
416 parse_std_timing_block(block);
419 static void parse_detailed_timing_block(unsigned char *block)
421 printk(" %d MHz ", PIXEL_CLOCK/1000000);
422 printk("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
423 H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
424 printk("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
425 V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
426 printk("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
427 (VSYNC_POSITIVE) ? "+" : "-");
430 int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
432 int i;
433 unsigned char *block;
435 if (edid == NULL || var == NULL)
436 return 1;
438 if (!(edid_checksum(edid)))
439 return 1;
441 if (!(edid_check_header(edid)))
442 return 1;
444 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
446 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
447 if (edid_is_timing_block(block)) {
448 var->xres = var->xres_virtual = H_ACTIVE;
449 var->yres = var->yres_virtual = V_ACTIVE;
450 var->height = var->width = -1;
451 var->right_margin = H_SYNC_OFFSET;
452 var->left_margin = (H_ACTIVE + H_BLANKING) -
453 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
454 var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
455 V_SYNC_WIDTH;
456 var->lower_margin = V_SYNC_OFFSET;
457 var->hsync_len = H_SYNC_WIDTH;
458 var->vsync_len = V_SYNC_WIDTH;
459 var->pixclock = PIXEL_CLOCK;
460 var->pixclock /= 1000;
461 var->pixclock = KHZ2PICOS(var->pixclock);
463 if (HSYNC_POSITIVE)
464 var->sync |= FB_SYNC_HOR_HIGH_ACT;
465 if (VSYNC_POSITIVE)
466 var->sync |= FB_SYNC_VERT_HIGH_ACT;
467 return 0;
470 return 1;
473 static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode)
475 struct fb_var_screeninfo var;
476 struct fb_info info;
478 var.xres = xres;
479 var.yres = yres;
480 fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
481 refresh, &var, &info);
482 mode->xres = xres;
483 mode->yres = yres;
484 mode->pixclock = var.pixclock;
485 mode->refresh = refresh;
486 mode->left_margin = var.left_margin;
487 mode->right_margin = var.right_margin;
488 mode->upper_margin = var.upper_margin;
489 mode->lower_margin = var.lower_margin;
490 mode->hsync_len = var.hsync_len;
491 mode->vsync_len = var.vsync_len;
492 mode->vmode = 0;
493 mode->sync = 0;
496 static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
498 int num = 0;
499 unsigned char c;
501 c = block[0];
502 if (c&0x80)
503 calc_mode_timings(720, 400, 70, &mode[num++]);
504 if (c&0x40)
505 calc_mode_timings(720, 400, 88, &mode[num++]);
506 if (c&0x20)
507 mode[num++] = vesa_modes[3];
508 if (c&0x10)
509 calc_mode_timings(640, 480, 67, &mode[num++]);
510 if (c&0x08)
511 mode[num++] = vesa_modes[4];
512 if (c&0x04)
513 mode[num++] = vesa_modes[5];
514 if (c&0x02)
515 mode[num++] = vesa_modes[7];
516 if (c&0x01)
517 mode[num++] = vesa_modes[8];
519 c = block[1];
520 if (c&0x80)
521 mode[num++] = vesa_modes[9];
522 if (c&0x40)
523 mode[num++] = vesa_modes[10];
524 if (c&0x20)
525 calc_mode_timings(832, 624, 75, &mode[num++]);
526 if (c&0x10)
527 mode[num++] = vesa_modes[12];
528 if (c&0x08)
529 mode[num++] = vesa_modes[13];
530 if (c&0x04)
531 mode[num++] = vesa_modes[14];
532 if (c&0x02)
533 mode[num++] = vesa_modes[15];
534 if (c&0x01)
535 mode[num++] = vesa_modes[21];
537 c = block[2];
538 if (c&0x80)
539 mode[num++] = vesa_modes[17];
541 return num;
544 static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
546 int xres, yres = 0, refresh, ratio, i;
548 xres = (block[0] + 31) * 8;
549 if (xres <= 256)
550 return 0;
552 ratio = (block[1] & 0xc0) >> 6;
553 switch (ratio) {
554 case 0:
555 yres = xres;
556 break;
557 case 1:
558 yres = (xres * 3)/4;
559 break;
560 case 2:
561 yres = (xres * 4)/5;
562 break;
563 case 3:
564 yres = (xres * 9)/16;
565 break;
567 refresh = (block[1] & 0x3f) + 60;
569 for (i = 0; i < VESA_MODEDB_SIZE; i++) {
570 if (vesa_modes[i].xres == xres &&
571 vesa_modes[i].yres == yres &&
572 vesa_modes[i].refresh == refresh) {
573 *mode = vesa_modes[i];
574 break;
575 } else {
576 calc_mode_timings(xres, yres, refresh, mode);
577 break;
580 return 1;
583 static int get_dst_timing(unsigned char *block,
584 struct fb_videomode *mode)
586 int j, num = 0;
588 for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE)
589 num += get_std_timing(block, &mode[num]);
591 return num;
594 static void get_detailed_timing(unsigned char *block,
595 struct fb_videomode *mode)
597 mode->xres = H_ACTIVE;
598 mode->yres = V_ACTIVE;
599 mode->pixclock = PIXEL_CLOCK;
600 mode->pixclock /= 1000;
601 mode->pixclock = KHZ2PICOS(mode->pixclock);
602 mode->right_margin = H_SYNC_OFFSET;
603 mode->left_margin = (H_ACTIVE + H_BLANKING) -
604 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
605 mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
606 V_SYNC_WIDTH;
607 mode->lower_margin = V_SYNC_OFFSET;
608 mode->hsync_len = H_SYNC_WIDTH;
609 mode->vsync_len = V_SYNC_WIDTH;
610 if (HSYNC_POSITIVE)
611 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
612 if (VSYNC_POSITIVE)
613 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
614 mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
615 (V_ACTIVE + V_BLANKING));
616 mode->vmode = 0;
620 * fb_create_modedb - create video mode database
621 * @edid: EDID data
622 * @dbsize: database size
624 * RETURNS: struct fb_videomode, @dbsize contains length of database
626 * DESCRIPTION:
627 * This function builds a mode database using the contents of the EDID
628 * data
630 struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
632 struct fb_videomode *mode, *m;
633 unsigned char *block;
634 int num = 0, i;
636 mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
637 if (mode == NULL)
638 return NULL;
639 memset(mode, 0, 50 * sizeof(struct fb_videomode));
641 if (edid == NULL || !edid_checksum(edid) ||
642 !edid_check_header(edid)) {
643 kfree(mode);
644 return NULL;
647 *dbsize = 0;
649 block = edid + ESTABLISHED_TIMING_1;
650 num += get_est_timing(block, &mode[num]);
652 block = edid + STD_TIMING_DESCRIPTIONS_START;
653 for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
654 num += get_std_timing(block, &mode[num]);
656 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
657 for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
658 if (block[0] == 0x00 && block[1] == 0x00) {
659 if (block[3] == 0xfa) {
660 num += get_dst_timing(block + 5, &mode[num]);
662 } else {
663 get_detailed_timing(block, &mode[num]);
664 num++;
668 /* Yikes, EDID data is totally useless */
669 if (!num) {
670 kfree(mode);
671 return NULL;
674 *dbsize = num;
675 m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
676 if (!m)
677 return mode;
678 memmove(m, mode, num * sizeof(struct fb_videomode));
679 kfree(mode);
680 return m;
684 * fb_destroy_modedb - destroys mode database
685 * @modedb: mode database to destroy
687 * DESCRIPTION:
688 * Destroy mode database created by fb_create_modedb
690 void fb_destroy_modedb(struct fb_videomode *modedb)
692 if (modedb)
693 kfree(modedb);
697 * fb_get_monitor_limits - get monitor operating limits
698 * @edid: EDID data
699 * @specs: fb_monspecs structure pointer
701 * DESCRIPTION:
702 * Gets monitor operating limits from EDID data and places them in
703 * @specs
705 int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
707 int i, retval = 1;
708 unsigned char *block;
710 if (edid == NULL || specs == NULL)
711 return 1;
713 if (!(edid_checksum(edid)))
714 return 1;
716 if (!(edid_check_header(edid)))
717 return 1;
719 memset(specs, 0, sizeof(struct fb_monspecs));
720 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
722 printk("Monitor Operating Limits: ");
723 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
724 if (edid_is_limits_block(block)) {
725 specs->hfmin = H_MIN_RATE * 1000;
726 specs->hfmax = H_MAX_RATE * 1000;
727 specs->vfmin = V_MIN_RATE;
728 specs->vfmax = V_MAX_RATE;
729 specs->dclkmax = (MAX_PIXEL_CLOCK != 10*0xff) ?
730 MAX_PIXEL_CLOCK * 1000000 : 0;
731 specs->gtf = (GTF_SUPPORT) ? 1 : 0;
732 specs->dpms = edid[DPMS_FLAGS];
733 retval = 0;
734 printk("From EDID\n");
735 break;
739 /* estimate monitor limits based on modes supported */
740 if (retval) {
741 struct fb_videomode *modes;
742 int num_modes, i, hz, hscan, pixclock;
744 modes = fb_create_modedb(edid, &num_modes);
745 if (!modes) {
746 printk("None Available\n");
747 return 1;
750 retval = 0;
751 for (i = 0; i < num_modes; i++) {
752 hz = modes[i].refresh;
753 pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
754 hscan = (modes[i].yres * 105 * hz + 5000)/100;
756 if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
757 specs->dclkmax = pixclock;
758 if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
759 specs->dclkmin = pixclock;
760 if (specs->hfmax == 0 || specs->hfmax < hscan)
761 specs->hfmax = hscan;
762 if (specs->hfmin == 0 || specs->hfmin > hscan)
763 specs->hfmin = hscan;
764 if (specs->vfmax == 0 || specs->vfmax < hz)
765 specs->vfmax = hz;
766 if (specs->vfmin == 0 || specs->vfmin > hz)
767 specs->vfmin = hz;
769 printk("Extrapolated\n");
770 fb_destroy_modedb(modes);
772 printk(" H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n", specs->hfmin/1000, specs->hfmax/1000,
773 specs->vfmin, specs->vfmax, specs->dclkmax/1000000);
774 return retval;
777 void show_edid(unsigned char *edid)
779 unsigned char *block;
780 int i;
782 if (edid == NULL)
783 return;
785 if (!(edid_checksum(edid)))
786 return;
788 if (!(edid_check_header(edid)))
789 return;
790 printk("========================================\n");
791 printk("Display Information (EDID)\n");
792 printk("========================================\n");
793 printk(" EDID Version %d.%d\n", (int) edid[EDID_STRUCT_VERSION],
794 (int) edid[EDID_STRUCT_REVISION]);
796 parse_vendor_block(edid + ID_MANUFACTURER_NAME);
798 printk(" Display Characteristics:\n");
799 parse_display_block(edid + EDID_STRUCT_DISPLAY);
801 printk(" Standard Timings\n");
802 block = edid + STD_TIMING_DESCRIPTIONS_START;
803 for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
804 parse_std_timing_block(block);
806 printk(" Supported VESA Modes\n");
807 parse_std_md_block(edid + ESTABLISHED_TIMING_1);
809 printk(" Detailed Monitor Information\n");
810 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
811 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
812 if (edid_is_serial_block(block)) {
813 parse_serial_block(block);
814 } else if (edid_is_ascii_block(block)) {
815 parse_ascii_block(block);
816 } else if (edid_is_limits_block(block)) {
817 parse_limits_block(block);
818 } else if (edid_is_monitor_block(block)) {
819 parse_monitor_block(block);
820 } else if (edid_is_color_block(block)) {
821 parse_color_block(block);
822 } else if (edid_is_std_timings_block(block)) {
823 parse_dst_timing_block(block);
824 } else if (edid_is_timing_block(block)) {
825 parse_detailed_timing_block(block);
828 printk("========================================\n");
831 #ifdef CONFIG_PPC_OF
832 char *get_EDID_from_OF(struct pci_dev *pdev)
834 static char *propnames[] =
835 { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
836 unsigned char *pedid = NULL;
837 struct device_node *dp;
838 int i;
840 if (pdev == NULL)
841 return NULL;
842 dp = pci_device_to_OF_node(pdev);
843 while (dp != NULL) {
844 for (i = 0; propnames[i] != NULL; ++i) {
845 pedid = (unsigned char *) get_property(dp, propnames[i], NULL);
846 if (pedid != NULL)
847 return pedid;
849 dp = dp->child;
851 show_edid(pedid);
852 return pedid;
854 #endif
856 #ifdef CONFIG_X86
857 char *get_EDID_from_BIOS(void *dummy)
859 unsigned char *pedid = edid_info.dummy;
861 if (!pedid)
862 return NULL;
863 show_edid(pedid);
864 return pedid;
866 #endif
869 * VESA Generalized Timing Formula (GTF)
872 #define FLYBACK 550
873 #define V_FRONTPORCH 1
874 #define H_OFFSET 40
875 #define H_SCALEFACTOR 20
876 #define H_BLANKSCALE 128
877 #define H_GRADIENT 600
878 #define C_VAL 30
879 #define M_VAL 300
881 struct __fb_timings {
882 u32 dclk;
883 u32 hfreq;
884 u32 vfreq;
885 u32 hactive;
886 u32 vactive;
887 u32 hblank;
888 u32 vblank;
889 u32 htotal;
890 u32 vtotal;
894 * a simple function to get the square root of integers
896 static u32 fb_sqrt(int x)
898 register int op, res, one;
900 op = x;
901 res = 0;
903 one = 1 << 30;
904 while (one > op) one >>= 2;
906 while (one != 0) {
907 if (op >= res + one) {
908 op = op - (res + one);
909 res = res + 2 * one;
911 res /= 2;
912 one /= 4;
914 return((u32) res);
918 * fb_get_vblank - get vertical blank time
919 * @hfreq: horizontal freq
921 * DESCRIPTION:
922 * vblank = right_margin + vsync_len + left_margin
924 * given: right_margin = 1 (V_FRONTPORCH)
925 * vsync_len = 3
926 * flyback = 550
928 * flyback * hfreq
929 * left_margin = --------------- - vsync_len
930 * 1000000
932 static u32 fb_get_vblank(u32 hfreq)
934 u32 vblank;
936 vblank = (hfreq * FLYBACK)/1000;
937 vblank = (vblank + 500)/1000;
938 return (vblank + V_FRONTPORCH);
941 /**
942 * fb_get_hblank_by_freq - get horizontal blank time given hfreq
943 * @hfreq: horizontal freq
944 * @xres: horizontal resolution in pixels
946 * DESCRIPTION:
948 * xres * duty_cycle
949 * hblank = ------------------
950 * 100 - duty_cycle
952 * duty cycle = percent of htotal assigned to inactive display
953 * duty cycle = C - (M/Hfreq)
955 * where: C = ((offset - scale factor) * blank_scale)
956 * -------------------------------------- + scale factor
957 * 256
958 * M = blank_scale * gradient
961 static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
963 u32 c_val, m_val, duty_cycle, hblank;
965 c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
966 H_SCALEFACTOR) * 1000;
967 m_val = (H_BLANKSCALE * H_GRADIENT)/256;
968 m_val = (m_val * 1000000)/hfreq;
969 duty_cycle = c_val - m_val;
970 hblank = (xres * duty_cycle)/(100000 - duty_cycle);
971 return (hblank);
974 /**
975 * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
976 * @dclk: pixelclock in Hz
977 * @xres: horizontal resolution in pixels
979 * DESCRIPTION:
981 * xres * duty_cycle
982 * hblank = ------------------
983 * 100 - duty_cycle
985 * duty cycle = percent of htotal assigned to inactive display
986 * duty cycle = C - (M * h_period)
988 * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
989 * -----------------------------------------------
990 * 2 * M
991 * M = 300;
992 * C = 30;
995 static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
997 u32 duty_cycle, h_period, hblank;;
999 dclk /= 1000;
1000 h_period = 100 - C_VAL;
1001 h_period *= h_period;
1002 h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
1003 h_period *=10000;
1005 h_period = fb_sqrt((int) h_period);
1006 h_period -= (100 - C_VAL) * 100;
1007 h_period *= 1000;
1008 h_period /= 2 * M_VAL;
1010 duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
1011 hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
1012 hblank &= ~15;
1013 return (hblank);
1017 * fb_get_hfreq - estimate hsync
1018 * @vfreq: vertical refresh rate
1019 * @yres: vertical resolution
1021 * DESCRIPTION:
1023 * (yres + front_port) * vfreq * 1000000
1024 * hfreq = -------------------------------------
1025 * (1000000 - (vfreq * FLYBACK)
1029 static u32 fb_get_hfreq(u32 vfreq, u32 yres)
1031 u32 divisor, hfreq;
1033 divisor = (1000000 - (vfreq * FLYBACK))/1000;
1034 hfreq = (yres + V_FRONTPORCH) * vfreq * 1000;
1035 return (hfreq/divisor);
1038 static void fb_timings_vfreq(struct __fb_timings *timings)
1040 timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
1041 timings->vblank = fb_get_vblank(timings->hfreq);
1042 timings->vtotal = timings->vactive + timings->vblank;
1043 timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
1044 timings->hactive);
1045 timings->htotal = timings->hactive + timings->hblank;
1046 timings->dclk = timings->htotal * timings->hfreq;
1049 static void fb_timings_hfreq(struct __fb_timings *timings)
1051 timings->vblank = fb_get_vblank(timings->hfreq);
1052 timings->vtotal = timings->vactive + timings->vblank;
1053 timings->vfreq = timings->hfreq/timings->vtotal;
1054 timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
1055 timings->hactive);
1056 timings->htotal = timings->hactive + timings->hblank;
1057 timings->dclk = timings->htotal * timings->hfreq;
1060 static void fb_timings_dclk(struct __fb_timings *timings)
1062 timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
1063 timings->hactive);
1064 timings->htotal = timings->hactive + timings->hblank;
1065 timings->hfreq = timings->dclk/timings->htotal;
1066 timings->vblank = fb_get_vblank(timings->hfreq);
1067 timings->vtotal = timings->vactive + timings->vblank;
1068 timings->vfreq = timings->hfreq/timings->vtotal;
1072 * fb_get_mode - calculates video mode using VESA GTF
1073 * @flags: if: 0 - maximize vertical refresh rate
1074 * 1 - vrefresh-driven calculation;
1075 * 2 - hscan-driven calculation;
1076 * 3 - pixelclock-driven calculation;
1077 * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
1078 * @var: pointer to fb_var_screeninfo
1079 * @info: pointer to fb_info
1081 * DESCRIPTION:
1082 * Calculates video mode based on monitor specs using VESA GTF.
1083 * The GTF is best for VESA GTF compliant monitors but is
1084 * specifically formulated to work for older monitors as well.
1086 * If @flag==0, the function will attempt to maximize the
1087 * refresh rate. Otherwise, it will calculate timings based on
1088 * the flag and accompanying value.
1090 * If FB_IGNOREMON bit is set in @flags, monitor specs will be
1091 * ignored and @var will be filled with the calculated timings.
1093 * All calculations are based on the VESA GTF Spreadsheet
1094 * available at VESA's public ftp (http://www.vesa.org).
1096 * NOTES:
1097 * The timings generated by the GTF will be different from VESA
1098 * DMT. It might be a good idea to keep a table of standard
1099 * VESA modes as well. The GTF may also not work for some displays,
1100 * such as, and especially, analog TV.
1102 * REQUIRES:
1103 * A valid info->monspecs, otherwise 'safe numbers' will be used.
1105 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
1107 struct __fb_timings timings;
1108 u32 interlace = 1, dscan = 1;
1109 u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
1112 * If monspecs are invalid, use values that are enough
1113 * for 640x480@60
1115 if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
1116 !info->monspecs.dclkmax ||
1117 info->monspecs.hfmax < info->monspecs.hfmin ||
1118 info->monspecs.vfmax < info->monspecs.vfmin ||
1119 info->monspecs.dclkmax < info->monspecs.dclkmin) {
1120 hfmin = 29000; hfmax = 30000;
1121 vfmin = 60; vfmax = 60;
1122 dclkmin = 0; dclkmax = 25000000;
1123 } else {
1124 hfmin = info->monspecs.hfmin;
1125 hfmax = info->monspecs.hfmax;
1126 vfmin = info->monspecs.vfmin;
1127 vfmax = info->monspecs.vfmax;
1128 dclkmin = info->monspecs.dclkmin;
1129 dclkmax = info->monspecs.dclkmax;
1132 memset(&timings, 0, sizeof(struct __fb_timings));
1133 timings.hactive = var->xres;
1134 timings.vactive = var->yres;
1135 if (var->vmode & FB_VMODE_INTERLACED) {
1136 timings.vactive /= 2;
1137 interlace = 2;
1139 if (var->vmode & FB_VMODE_DOUBLE) {
1140 timings.vactive *= 2;
1141 dscan = 2;
1144 switch (flags & ~FB_IGNOREMON) {
1145 case FB_MAXTIMINGS: /* maximize refresh rate */
1146 timings.hfreq = hfmax;
1147 fb_timings_hfreq(&timings);
1148 if (timings.vfreq > vfmax) {
1149 timings.vfreq = vfmax;
1150 fb_timings_vfreq(&timings);
1152 if (timings.dclk > dclkmax) {
1153 timings.dclk = dclkmax;
1154 fb_timings_dclk(&timings);
1156 break;
1157 case FB_VSYNCTIMINGS: /* vrefresh driven */
1158 timings.vfreq = val;
1159 fb_timings_vfreq(&timings);
1160 break;
1161 case FB_HSYNCTIMINGS: /* hsync driven */
1162 timings.hfreq = val;
1163 fb_timings_hfreq(&timings);
1164 break;
1165 case FB_DCLKTIMINGS: /* pixelclock driven */
1166 timings.dclk = PICOS2KHZ(val) * 1000;
1167 fb_timings_dclk(&timings);
1168 break;
1169 default:
1170 return -EINVAL;
1174 if (!(flags & FB_IGNOREMON) &&
1175 (timings.vfreq < vfmin || timings.vfreq > vfmax ||
1176 timings.hfreq < hfmin || timings.hfreq > hfmax ||
1177 timings.dclk < dclkmin || timings.dclk > dclkmax))
1178 return -EINVAL;
1180 var->pixclock = KHZ2PICOS(timings.dclk/1000);
1181 var->hsync_len = (timings.htotal * 8)/100;
1182 var->right_margin = (timings.hblank/2) - var->hsync_len;
1183 var->left_margin = timings.hblank - var->right_margin - var->hsync_len;
1185 var->vsync_len = (3 * interlace)/dscan;
1186 var->lower_margin = (1 * interlace)/dscan;
1187 var->upper_margin = (timings.vblank * interlace)/dscan -
1188 (var->vsync_len + var->lower_margin);
1190 return 0;
1194 * fb_validate_mode - validates var against monitor capabilities
1195 * @var: pointer to fb_var_screeninfo
1196 * @info: pointer to fb_info
1198 * DESCRIPTION:
1199 * Validates video mode against monitor capabilities specified in
1200 * info->monspecs.
1202 * REQUIRES:
1203 * A valid info->monspecs.
1205 int fb_validate_mode(struct fb_var_screeninfo *var, struct fb_info *info)
1207 u32 hfreq, vfreq, htotal, vtotal, pixclock;
1208 u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
1211 * If monspecs are invalid, use values that are enough
1212 * for 640x480@60
1214 if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
1215 !info->monspecs.dclkmax ||
1216 info->monspecs.hfmax < info->monspecs.hfmin ||
1217 info->monspecs.vfmax < info->monspecs.vfmin ||
1218 info->monspecs.dclkmax < info->monspecs.dclkmin) {
1219 hfmin = 29000; hfmax = 30000;
1220 vfmin = 60; vfmax = 60;
1221 dclkmin = 0; dclkmax = 25000000;
1222 } else {
1223 hfmin = info->monspecs.hfmin;
1224 hfmax = info->monspecs.hfmax;
1225 vfmin = info->monspecs.vfmin;
1226 vfmax = info->monspecs.vfmax;
1227 dclkmin = info->monspecs.dclkmin;
1228 dclkmax = info->monspecs.dclkmax;
1231 if (!var->pixclock)
1232 return -EINVAL;
1233 pixclock = PICOS2KHZ(var->pixclock) * 1000;
1235 htotal = var->xres + var->right_margin + var->hsync_len +
1236 var->left_margin;
1237 vtotal = var->yres + var->lower_margin + var->vsync_len +
1238 var->upper_margin;
1240 if (var->vmode & FB_VMODE_INTERLACED)
1241 vtotal /= 2;
1242 if (var->vmode & FB_VMODE_DOUBLE)
1243 vtotal *= 2;
1245 hfreq = pixclock/htotal;
1246 vfreq = hfreq/vtotal;
1248 return (vfreq < vfmin || vfreq > vfmax ||
1249 hfreq < hfmin || hfreq > hfmax ||
1250 pixclock < dclkmin || pixclock > dclkmax) ?
1251 -EINVAL : 0;
1254 EXPORT_SYMBOL(parse_edid);
1255 EXPORT_SYMBOL(show_edid);
1256 #ifdef CONFIG_X86
1257 EXPORT_SYMBOL(get_EDID_from_BIOS);
1258 #endif
1259 #ifdef CONFIG_PPC_OF
1260 EXPORT_SYMBOL(get_EDID_from_OF);
1261 #endif
1262 EXPORT_SYMBOL(fb_get_monitor_limits);
1263 EXPORT_SYMBOL(fb_get_mode);
1264 EXPORT_SYMBOL(fb_validate_mode);
1265 EXPORT_SYMBOL(fb_create_modedb);
1266 EXPORT_SYMBOL(fb_destroy_modedb);