Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / ddc / interpret_edid.c
1 /*
2 * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
3 * Copyright 2007 Red Hat, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * interpret_edid.c: interpret a primary EDID block
25 */
26
27 #ifdef HAVE_XORG_CONFIG_H
28 #include <xorg-config.h>
29 #endif
30
31 #include "misc.h"
32 #include "xf86.h"
33 #include "xf86_OSproc.h"
34 #define _PARSE_EDID_
35 #include "xf86DDC.h"
36 #include <string.h>
37
38 static void get_vendor_section(Uchar *, struct vendor *);
39 static void get_version_section(Uchar *, struct edid_version *);
40 static void get_display_section(Uchar *, struct disp_features *,
41 struct edid_version *);
42 static void get_established_timing_section(Uchar *,
43 struct established_timings *);
44 static void get_std_timing_section(Uchar *, struct std_timings *,
45 struct edid_version *);
46 static void fetch_detailed_block(Uchar * c, struct edid_version *ver,
47 struct detailed_monitor_section *det_mon);
48 static void get_dt_md_section(Uchar *, struct edid_version *,
49 struct detailed_monitor_section *det_mon);
50 static void copy_string(Uchar *, Uchar *);
51 static void get_dst_timing_section(Uchar *, struct std_timings *,
52 struct edid_version *);
53 static void get_monitor_ranges(Uchar *, struct monitor_ranges *);
54 static void get_whitepoint_section(Uchar *, struct whitePoints *);
55 static void get_detailed_timing_section(Uchar *, struct detailed_timings *);
56 static Bool validate_version(int scrnIndex, struct edid_version *);
57
58 static void
59 find_ranges_section(struct detailed_monitor_section *det, void *ranges)
60 {
61 if (det->type == DS_RANGES && det->section.ranges.max_clock)
62 *(struct monitor_ranges **) ranges = &det->section.ranges;
63 }
64
65 static void
66 find_max_detailed_clock(struct detailed_monitor_section *det, void *ret)
67 {
68 if (det->type == DT) {
69 *(int *) ret = max(*((int *) ret), det->section.d_timings.clock);
70 }
71 }
72
73 static void
74 handle_edid_quirks(xf86MonPtr m)
75 {
76 struct monitor_ranges *ranges = NULL;
77
78 /*
79 * max_clock is only encoded in EDID in tens of MHz, so occasionally we
80 * find a monitor claiming a max of 160 with a mode requiring 162, or
81 * similar. Strictly we should refuse to round up too far, but let's
82 * see how well this works.
83 */
84
85 /* Try to find Monitor Range and max clock, then re-set range value */
86 xf86ForEachDetailedBlock(m, find_ranges_section, &ranges);
87 if (ranges && ranges->max_clock) {
88 int clock = 0;
89
90 xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock);
91 if (clock && (ranges->max_clock * 1e6 < clock)) {
92 xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max "
93 "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock);
94 ranges->max_clock = (clock + 999999) / 1e6;
95 }
96 }
97 }
98
99 struct det_hv_parameter {
100 int real_hsize;
101 int real_vsize;
102 float target_aspect;
103 };
104
105 static void
106 handle_detailed_hvsize(struct detailed_monitor_section *det_mon, void *data)
107 {
108 struct det_hv_parameter *p = (struct det_hv_parameter *) data;
109 float timing_aspect;
110
111 if (det_mon->type == DT) {
112 struct detailed_timings *timing;
113
114 timing = &det_mon->section.d_timings;
115
116 if (!timing->v_size)
117 return;
118
119 timing_aspect = (float) timing->h_size / timing->v_size;
120 if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) {
121 p->real_hsize = max(p->real_hsize, timing->h_size);
122 p->real_vsize = max(p->real_vsize, timing->v_size);
123 }
124 }
125 }
126
127 static void
128 encode_aspect_ratio(xf86MonPtr m)
129 {
130 /*
131 * some monitors encode the aspect ratio instead of the physical size.
132 * try to find the largest detailed timing that matches that aspect
133 * ratio and use that to fill in the feature section.
134 */
135 if ((m->features.hsize == 16 && m->features.vsize == 9) ||
136 (m->features.hsize == 16 && m->features.vsize == 10) ||
137 (m->features.hsize == 4 && m->features.vsize == 3) ||
138 (m->features.hsize == 5 && m->features.vsize == 4)) {
139
140 struct det_hv_parameter p;
141
142 p.real_hsize = 0;
143 p.real_vsize = 0;
144 p.target_aspect = (float) m->features.hsize / m->features.vsize;
145
146 xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p);
147
148 if (!p.real_hsize || !p.real_vsize) {
149 m->features.hsize = m->features.vsize = 0;
150 }
151 else if ((m->features.hsize * 10 == p.real_hsize) &&
152 (m->features.vsize * 10 == p.real_vsize)) {
153 /* exact match is just unlikely, should do a better check though */
154 m->features.hsize = m->features.vsize = 0;
155 }
156 else {
157 /* convert mm to cm */
158 m->features.hsize = (p.real_hsize + 5) / 10;
159 m->features.vsize = (p.real_vsize + 5) / 10;
160 }
161
162 xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n",
163 m->features.hsize, m->features.vsize);
164 }
165 }
166
167 xf86MonPtr
168 xf86InterpretEDID(int scrnIndex, Uchar * block)
169 {
170 xf86MonPtr m;
171
172 if (!block)
173 return NULL;
174 if (!(m = xnfcalloc(sizeof(xf86Monitor), 1)))
175 return NULL;
176 m->scrnIndex = scrnIndex;
177 m->rawData = block;
178
179 get_vendor_section(SECTION(VENDOR_SECTION, block), &m->vendor);
180 get_version_section(SECTION(VERSION_SECTION, block), &m->ver);
181 if (!validate_version(scrnIndex, &m->ver))
182 goto error;
183 get_display_section(SECTION(DISPLAY_SECTION, block), &m->features, &m->ver);
184 get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION, block),
185 &m->timings1);
186 get_std_timing_section(SECTION(STD_TIMING_SECTION, block), m->timings2,
187 &m->ver);
188 get_dt_md_section(SECTION(DET_TIMING_SECTION, block), &m->ver, m->det_mon);
189 m->no_sections = (int) *(char *) SECTION(NO_EDID, block);
190
191 handle_edid_quirks(m);
192 encode_aspect_ratio(m);
193
194 return m;
195
196 error:
197 free(m);
198 return NULL;
199 }
200
201 static int
202 get_cea_detail_timing(Uchar * blk, xf86MonPtr mon,
203 struct detailed_monitor_section *det_mon)
204 {
205 int dt_num;
206 int dt_offset = ((struct cea_ext_body *) blk)->dt_offset;
207
208 dt_num = 0;
209
210 if (dt_offset < CEA_EXT_MIN_DATA_OFFSET)
211 return dt_num;
212
213 for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) &&
214 dt_num < CEA_EXT_DET_TIMING_NUM; _NEXT_DT_MD_SECTION(dt_offset)) {
215
216 fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num);
217 dt_num = dt_num + 1;
218 }
219
220 return dt_num;
221 }
222
223 static void
224 handle_cea_detail_block(Uchar * ext, xf86MonPtr mon,
225 handle_detailed_fn fn, void *data)
226 {
227 int i;
228 struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM];
229 int det_mon_num;
230
231 det_mon_num = get_cea_detail_timing(ext, mon, det_mon);
232
233 for (i = 0; i < det_mon_num; i++)
234 fn(det_mon + i, data);
235 }
236
237 void
238 xf86ForEachDetailedBlock(xf86MonPtr mon, handle_detailed_fn fn, void *data)
239 {
240 int i;
241 Uchar *ext;
242
243 if (mon == NULL)
244 return;
245
246 for (i = 0; i < DET_TIMINGS; i++)
247 fn(mon->det_mon + i, data);
248
249 for (i = 0; i < mon->no_sections; i++) {
250 ext = mon->rawData + EDID1_LEN * (i + 1);
251 switch (ext[EXT_TAG]) {
252 case CEA_EXT:
253 handle_cea_detail_block(ext, mon, fn, data);
254 break;
255 case VTB_EXT:
256 case DI_EXT:
257 case LS_EXT:
258 case MI_EXT:
259 break;
260 }
261 }
262 }
263
264 static struct cea_data_block *
265 extract_cea_data_block(Uchar * ext, int data_type)
266 {
267 struct cea_ext_body *cea;
268 struct cea_data_block *data_collection;
269 struct cea_data_block *data_end;
270
271 cea = (struct cea_ext_body *) ext;
272
273 if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET)
274 return NULL;
275
276 data_collection = &cea->data_collection;
277 data_end = (struct cea_data_block *) (cea->dt_offset + ext);
278
279 for (; data_collection < data_end;) {
280
281 if (data_type == data_collection->tag) {
282 return data_collection;
283 }
284 data_collection = (void *) ((unsigned char *) data_collection +
285 data_collection->len + 1);
286 }
287
288 return NULL;
289 }
290
291 static void
292 handle_cea_video_block(Uchar * ext, handle_video_fn fn, void *data)
293 {
294 struct cea_video_block *video;
295 struct cea_video_block *video_end;
296 struct cea_data_block *data_collection;
297
298 data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK);
299 if (data_collection == NULL)
300 return;
301
302 video = &data_collection->u.video;
303 video_end = (struct cea_video_block *)
304 ((Uchar *) video + data_collection->len);
305
306 for (; video < video_end; video = video + 1) {
307 fn(video, data);
308 }
309 }
310
311 void
312 xf86ForEachVideoBlock(xf86MonPtr mon, handle_video_fn fn, void *data)
313 {
314 int i;
315 Uchar *ext;
316
317 if (mon == NULL)
318 return;
319
320 for (i = 0; i < mon->no_sections; i++) {
321 ext = mon->rawData + EDID1_LEN * (i + 1);
322 switch (ext[EXT_TAG]) {
323 case CEA_EXT:
324 handle_cea_video_block(ext, fn, data);
325 break;
326 case VTB_EXT:
327 case DI_EXT:
328 case LS_EXT:
329 case MI_EXT:
330 break;
331 }
332 }
333 }
334
335 xf86MonPtr
336 xf86InterpretEEDID(int scrnIndex, Uchar * block)
337 {
338 xf86MonPtr m;
339
340 m = xf86InterpretEDID(scrnIndex, block);
341 if (!m)
342 return NULL;
343
344 /* extension parse */
345
346 return m;
347 }
348
349 static void
350 get_vendor_section(Uchar * c, struct vendor *r)
351 {
352 r->name[0] = L1;
353 r->name[1] = L2;
354 r->name[2] = L3;
355 r->name[3] = '\0';
356
357 r->prod_id = PROD_ID;
358 r->serial = SERIAL_NO;
359 r->week = WEEK;
360 r->year = YEAR;
361 }
362
363 static void
364 get_version_section(Uchar * c, struct edid_version *r)
365 {
366 r->version = VERSION;
367 r->revision = REVISION;
368 }
369
370 static void
371 get_display_section(Uchar * c, struct disp_features *r, struct edid_version *v)
372 {
373 r->input_type = INPUT_TYPE;
374 if (!DIGITAL(r->input_type)) {
375 r->input_voltage = INPUT_VOLTAGE;
376 r->input_setup = SETUP;
377 r->input_sync = SYNC;
378 }
379 else if (v->revision == 2 || v->revision == 3) {
380 r->input_dfp = DFP;
381 }
382 else if (v->revision >= 4) {
383 r->input_bpc = BPC;
384 r->input_interface = DIGITAL_INTERFACE;
385 }
386 r->hsize = HSIZE_MAX;
387 r->vsize = VSIZE_MAX;
388 r->gamma = GAMMA;
389 r->dpms = DPMS;
390 r->display_type = DISPLAY_TYPE;
391 r->msc = MSC;
392 r->redx = REDX;
393 r->redy = REDY;
394 r->greenx = GREENX;
395 r->greeny = GREENY;
396 r->bluex = BLUEX;
397 r->bluey = BLUEY;
398 r->whitex = WHITEX;
399 r->whitey = WHITEY;
400 }
401
402 static void
403 get_established_timing_section(Uchar * c, struct established_timings *r)
404 {
405 r->t1 = T1;
406 r->t2 = T2;
407 r->t_manu = T_MANU;
408 }
409
410 static void
411 get_cvt_timing_section(Uchar * c, struct cvt_timings *r)
412 {
413 int i;
414
415 for (i = 0; i < 4; i++) {
416 if (c[0] && c[1] && c[2]) {
417 r[i].height = (c[0] + ((c[1] & 0xF0) << 8) + 1) * 2;
418 switch (c[1] & 0xc0) {
419 case 0x00:
420 r[i].width = r[i].height * 4 / 3;
421 break;
422 case 0x40:
423 r[i].width = r[i].height * 16 / 9;
424 break;
425 case 0x80:
426 r[i].width = r[i].height * 16 / 10;
427 break;
428 case 0xc0:
429 r[i].width = r[i].height * 15 / 9;
430 break;
431 }
432 switch (c[2] & 0x60) {
433 case 0x00:
434 r[i].rate = 50;
435 break;
436 case 0x20:
437 r[i].rate = 60;
438 break;
439 case 0x40:
440 r[i].rate = 75;
441 break;
442 case 0x60:
443 r[i].rate = 85;
444 break;
445 }
446 r[i].rates = c[2] & 0x1f;
447 }
448 else {
449 return;
450 }
451 c += 3;
452 }
453 }
454
455 static void
456 get_std_timing_section(Uchar * c, struct std_timings *r, struct edid_version *v)
457 {
458 int i;
459
460 for (i = 0; i < STD_TIMINGS; i++) {
461 if (VALID_TIMING) {
462 r[i].hsize = HSIZE1;
463 VSIZE1(r[i].vsize);
464 r[i].refresh = REFRESH_R;
465 r[i].id = STD_TIMING_ID;
466 }
467 else {
468 r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0;
469 }
470 NEXT_STD_TIMING;
471 }
472 }
473
474 static const unsigned char empty_block[18];
475
476 static void
477 fetch_detailed_block(Uchar * c, struct edid_version *ver,
478 struct detailed_monitor_section *det_mon)
479 {
480 if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) {
481 switch (MONITOR_DESC_TYPE) {
482 case SERIAL_NUMBER:
483 det_mon->type = DS_SERIAL;
484 copy_string(c, det_mon->section.serial);
485 break;
486 case ASCII_STR:
487 det_mon->type = DS_ASCII_STR;
488 copy_string(c, det_mon->section.ascii_data);
489 break;
490 case MONITOR_RANGES:
491 det_mon->type = DS_RANGES;
492 get_monitor_ranges(c, &det_mon->section.ranges);
493 break;
494 case MONITOR_NAME:
495 det_mon->type = DS_NAME;
496 copy_string(c, det_mon->section.name);
497 break;
498 case ADD_COLOR_POINT:
499 det_mon->type = DS_WHITE_P;
500 get_whitepoint_section(c, det_mon->section.wp);
501 break;
502 case ADD_STD_TIMINGS:
503 det_mon->type = DS_STD_TIMINGS;
504 get_dst_timing_section(c, det_mon->section.std_t, ver);
505 break;
506 case COLOR_MANAGEMENT_DATA:
507 det_mon->type = DS_CMD;
508 break;
509 case CVT_3BYTE_DATA:
510 det_mon->type = DS_CVT;
511 get_cvt_timing_section(c, det_mon->section.cvt);
512 break;
513 case ADD_EST_TIMINGS:
514 det_mon->type = DS_EST_III;
515 memcpy(det_mon->section.est_iii, c + 6, 6);
516 break;
517 case ADD_DUMMY:
518 det_mon->type = DS_DUMMY;
519 break;
520 default:
521 det_mon->type = DS_UNKOWN;
522 break;
523 }
524 if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) {
525 det_mon->type = DS_VENDOR + c[3];
526 }
527 }
528 else {
529 det_mon->type = DT;
530 get_detailed_timing_section(c, &det_mon->section.d_timings);
531 }
532 }
533
534 static void
535 get_dt_md_section(Uchar * c, struct edid_version *ver,
536 struct detailed_monitor_section *det_mon)
537 {
538 int i;
539
540 for (i = 0; i < DET_TIMINGS; i++) {
541 fetch_detailed_block(c, ver, det_mon + i);
542 NEXT_DT_MD_SECTION;
543 }
544 }
545
546 static void
547 copy_string(Uchar * c, Uchar * s)
548 {
549 int i;
550
551 c = c + 5;
552 for (i = 0; (i < 13 && *c != 0x0A); i++)
553 *(s++) = *(c++);
554 *s = 0;
555 while (i-- && (*--s == 0x20))
556 *s = 0;
557 }
558
559 static void
560 get_dst_timing_section(Uchar * c, struct std_timings *t, struct edid_version *v)
561 {
562 int j;
563
564 c = c + 5;
565 for (j = 0; j < 5; j++) {
566 t[j].hsize = HSIZE1;
567 VSIZE1(t[j].vsize);
568 t[j].refresh = REFRESH_R;
569 t[j].id = STD_TIMING_ID;
570 NEXT_STD_TIMING;
571 }
572 }
573
574 static void
575 get_monitor_ranges(Uchar * c, struct monitor_ranges *r)
576 {
577 r->min_v = MIN_V;
578 r->max_v = MAX_V;
579 r->min_h = MIN_H;
580 r->max_h = MAX_H;
581 r->max_clock = 0;
582 if (MAX_CLOCK != 0xff) /* is specified? */
583 r->max_clock = MAX_CLOCK * 10 + 5;
584 if (HAVE_2ND_GTF) {
585 r->gtf_2nd_f = F_2ND_GTF;
586 r->gtf_2nd_c = C_2ND_GTF;
587 r->gtf_2nd_m = M_2ND_GTF;
588 r->gtf_2nd_k = K_2ND_GTF;
589 r->gtf_2nd_j = J_2ND_GTF;
590 }
591 else {
592 r->gtf_2nd_f = 0;
593 }
594 if (HAVE_CVT) {
595 r->max_clock_khz = MAX_CLOCK_KHZ;
596 r->max_clock = r->max_clock_khz / 1000;
597 r->maxwidth = MAXWIDTH;
598 r->supported_aspect = SUPPORTED_ASPECT;
599 r->preferred_aspect = PREFERRED_ASPECT;
600 r->supported_blanking = SUPPORTED_BLANKING;
601 r->supported_scaling = SUPPORTED_SCALING;
602 r->preferred_refresh = PREFERRED_REFRESH;
603 }
604 else {
605 r->max_clock_khz = 0;
606 }
607 }
608
609 static void
610 get_whitepoint_section(Uchar * c, struct whitePoints *wp)
611 {
612 wp[0].white_x = WHITEX1;
613 wp[0].white_y = WHITEY1;
614 wp[1].white_x = WHITEX2;
615 wp[1].white_y = WHITEY2;
616 wp[0].index = WHITE_INDEX1;
617 wp[1].index = WHITE_INDEX2;
618 wp[0].white_gamma = WHITE_GAMMA1;
619 wp[1].white_gamma = WHITE_GAMMA2;
620 }
621
622 static void
623 get_detailed_timing_section(Uchar * c, struct detailed_timings *r)
624 {
625 r->clock = PIXEL_CLOCK;
626 r->h_active = H_ACTIVE;
627 r->h_blanking = H_BLANK;
628 r->v_active = V_ACTIVE;
629 r->v_blanking = V_BLANK;
630 r->h_sync_off = H_SYNC_OFF;
631 r->h_sync_width = H_SYNC_WIDTH;
632 r->v_sync_off = V_SYNC_OFF;
633 r->v_sync_width = V_SYNC_WIDTH;
634 r->h_size = H_SIZE;
635 r->v_size = V_SIZE;
636 r->h_border = H_BORDER;
637 r->v_border = V_BORDER;
638 r->interlaced = INTERLACED;
639 r->stereo = STEREO;
640 r->stereo_1 = STEREO1;
641 r->sync = SYNC_T;
642 r->misc = MISC;
643 }
644
645 #define MAX_EDID_MINOR 4
646
647 static Bool
648 validate_version(int scrnIndex, struct edid_version *r)
649 {
650 if (r->version != 1) {
651 xf86DrvMsg(scrnIndex, X_ERROR, "Unknown EDID version %d\n", r->version);
652 return FALSE;
653 }
654
655 if (r->revision > MAX_EDID_MINOR)
656 xf86DrvMsg(scrnIndex, X_WARNING,
657 "Assuming version 1.%d is compatible with 1.%d\n",
658 r->revision, MAX_EDID_MINOR);
659
660 return TRUE;
661 }
662
663 /*
664 * Returns true if HDMI, false if definitely not or unknown.
665 */
666 Bool
667 xf86MonitorIsHDMI(xf86MonPtr mon)
668 {
669 int i = 0, version, offset;
670 char *edid = NULL;
671
672 if (!mon)
673 return FALSE;
674
675 if (!(mon->flags & EDID_COMPLETE_RAWDATA))
676 return FALSE;
677
678 if (!mon->no_sections)
679 return FALSE;
680
681 edid = (char *) mon->rawData;
682 if (!edid)
683 return FALSE;
684
685 /* find the CEA extension block */
686 for (i = 1; i <= mon->no_sections; i++)
687 if (edid[i * 128] == 0x02)
688 break;
689 if (i == mon->no_sections + 1)
690 return FALSE;
691 edid += (i * 128);
692
693 version = edid[1];
694 offset = edid[2];
695 if (version < 3 || offset < 4)
696 return FALSE;
697
698 /* walk the cea data blocks */
699 for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) {
700 char *x = edid + i;
701
702 /* find a vendor specific block */
703 if ((x[0] & 0xe0) >> 5 == 0x03) {
704 int oui = (x[3] << 16) + (x[2] << 8) + x[1];
705
706 /* find the HDMI vendor OUI */
707 if (oui == 0x000c03)
708 return TRUE;
709 }
710 }
711
712 /* guess it's not HDMI after all */
713 return FALSE;
714 }