through the unified interface find ranges section, max time clock and horizon & vertical size respectively.
--- hw/xfree86/ddc/interpret_edid.c | 120 +++++++++++++++++++++++---------------- 1 files changed, 72 insertions(+), 48 deletions(-) diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c index f04c6bc..d2a9fb4 100644 --- a/hw/xfree86/ddc/interpret_edid.c +++ b/hw/xfree86/ddc/interpret_edid.c @@ -54,11 +54,25 @@ static void get_detailed_timing_section(Uchar*, struct detailed_timings *); static Bool validate_version(int scrnIndex, struct edid_version *); static void +find_ranges_section(struct detailed_monitor_section *det, void *ranges) +{ + if (det->type == DS_RANGES && det->section.ranges.max_clock) + *(struct monitor_ranges **)ranges = &det->section.ranges; +} + +static void +find_max_detailed_clock(struct detailed_monitor_section *det, void *ret) +{ + if (det->type == DT) { + *(int *)ret = max(*((int *)ret), + det->section.d_timings.clock); + } +} + +static void handle_edid_quirks(xf86MonPtr m) { - int i, j; - struct detailed_timings *preferred_timing; - struct monitor_ranges *ranges; + struct monitor_ranges *ranges = NULL; /* * max_clock is only encoded in EDID in tens of MHz, so occasionally we @@ -66,28 +80,49 @@ handle_edid_quirks(xf86MonPtr m) * similar. Strictly we should refuse to round up too far, but let's * see how well this works. */ - for (i = 0; i < 4; i++) { - if (m->det_mon[i].type == DS_RANGES) { - ranges = &m->det_mon[i].section.ranges; - for (j = 0; j < 4; j++) { - if (m->det_mon[j].type == DT) { - preferred_timing = &m->det_mon[j].section.d_timings; - if (!ranges->max_clock) continue; /* zero is legal */ - if (ranges->max_clock * 1000000 < preferred_timing->clock) { - xf86Msg(X_WARNING, - "EDID preferred timing clock %.2fMHz exceeds " - "claimed max %dMHz, fixing\n", - preferred_timing->clock / 1.0e6, - ranges->max_clock); - ranges->max_clock = - (preferred_timing->clock+999999)/1000000; - return; - } - } - } - } + + /* Try to find Monitor Range and max clock, then re-set range value*/ + xf86ForEachDetailedBlock(m, find_ranges_section, &ranges); + if (ranges && ranges->max_clock) { + int clock = 0; + xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock); + if (clock && (ranges->max_clock * 1e6 < clock)) { + xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max " + "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock); + ranges->max_clock = (clock+999999)/1e6; + } + } +} + +struct det_hv_parameter { + int real_hsize; + int real_vsize; + float target_aspect; +}; + +static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon, + void *data) +{ + struct det_hv_parameter *p = (struct det_hv_parameter *)data; + float timing_aspect; + + if (det_mon->type == DT) { + struct detailed_timings *timing; + timing = &det_mon->section.d_timings; + + if (!timing->v_size) + return; + + timing_aspect = (float)timing->h_size / timing->v_size; + if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) { + p->real_hsize = max(p->real_hsize, timing->h_size); + p->real_vsize = max(p->real_vsize, timing->v_size); + } } +} +static void encode_aspect_ratio(xf86MonPtr m) +{ /* * some monitors encode the aspect ratio instead of the physical size. * try to find the largest detailed timing that matches that aspect @@ -97,38 +132,26 @@ handle_edid_quirks(xf86MonPtr m) (m->features.hsize == 16 && m->features.vsize == 10) || (m->features.hsize == 4 && m->features.vsize == 3) || (m->features.hsize == 5 && m->features.vsize == 4)) { - int real_hsize = 0, real_vsize = 0; - float target_aspect, timing_aspect; - - target_aspect = (float)m->features.hsize / (float)m->features.vsize; - for (i = 0; i < 4; i++) { - if (m->det_mon[i].type == DT) { - struct detailed_timings *timing; - timing = &m->det_mon[i].section.d_timings; - - if (!timing->v_size) - continue; - - timing_aspect = (float)timing->h_size / (float)timing->v_size; - if (fabs(1 - (timing_aspect / target_aspect)) < 0.05) { - real_hsize = max(real_hsize, timing->h_size); - real_vsize = max(real_vsize, timing->v_size); - } - } - } - if (!real_hsize || !real_vsize) { + struct det_hv_parameter p; + p.real_hsize = 0; + p.real_vsize = 0; + p.target_aspect = (float)m->features.hsize /m->features.vsize; + + xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p); + + if (!p.real_hsize || !p.real_vsize) { m->features.hsize = m->features.vsize = 0; - } else if ((m->features.hsize * 10 == real_hsize) && - (m->features.vsize * 10 == real_vsize)) { + } else if ((m->features.hsize * 10 == p.real_hsize) && + (m->features.vsize * 10 == p.real_vsize)) { /* exact match is just unlikely, should do a better check though */ m->features.hsize = m->features.vsize = 0; } else { /* convert mm to cm */ - m->features.hsize = (real_hsize + 5) / 10; - m->features.vsize = (real_vsize + 5) / 10; + m->features.hsize = (p.real_hsize + 5) / 10; + m->features.vsize = (p.real_vsize + 5) / 10; } - + xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n", m->features.hsize, m->features.vsize); } @@ -157,6 +180,7 @@ xf86InterpretEDID(int scrnIndex, Uchar *block) m->no_sections = (int)*(char *)SECTION(NO_EDID,block); handle_edid_quirks(m); + encode_aspect_ratio(m); return (m); -- 1.5.4.4 _______________________________________________ xorg mailing list xorg@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xorg