diff options
-rw-r--r-- | edid-decode.cpp | 20 | ||||
-rw-r--r-- | edid-decode.h | 5 | ||||
-rw-r--r-- | parse-base-block.cpp | 13 | ||||
-rw-r--r-- | parse-cta-block.cpp | 27 |
4 files changed, 46 insertions, 19 deletions
diff --git a/edid-decode.cpp b/edid-decode.cpp index 0473bbf..94ea330 100644 --- a/edid-decode.cpp +++ b/edid-decode.cpp @@ -394,6 +394,9 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t, if (t->interlaced) vact /= 2; + if (t->ycbcr420) + hor_freq_khz /= 2; + double vtotal = vact + vbl; bool ok = true; @@ -427,6 +430,7 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t, add_str(s, std::to_string(t->hsize_mm) + " mm x " + std::to_string(t->vsize_mm) + " mm"); if (!s.empty()) s = " (" + s + ")"; + unsigned pixclk_khz = t->pixclk_khz / (t->ycbcr420 ? 2 : 1); char buf[10]; @@ -437,16 +441,16 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t, refresh, t->hratio, t->vratio, hor_freq_khz, - t->pixclk_khz / 1000.0, + pixclk_khz / 1000.0, s.c_str()); unsigned len = strlen(prefix) + 2; - if (detailed && options[OptXModeLineTimings]) + if (!t->ycbcr420 && detailed && options[OptXModeLineTimings]) print_modeline(len, t, refresh); - else if (detailed && options[OptFBModeTimings]) + else if (!t->ycbcr420 && detailed && options[OptFBModeTimings]) print_fbmode(len, t, refresh, hor_freq_khz); - else if (detailed && options[OptV4L2Timings]) + else if (!t->ycbcr420 && detailed && options[OptV4L2Timings]) print_v4l2_timing(t, refresh, type); else if (detailed) print_detailed_timing(len + strlen(type) + 6, t); @@ -475,10 +479,10 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t, min_vert_freq_hz = min(min_vert_freq_hz, refresh); max_vert_freq_hz = max(max_vert_freq_hz, refresh); } - if (t->pixclk_khz && (t->hact + hbl)) { - min_hor_freq_hz = min(min_hor_freq_hz, (t->pixclk_khz * 1000) / (t->hact + hbl)); - max_hor_freq_hz = max(max_hor_freq_hz, (t->pixclk_khz * 1000) / (t->hact + hbl)); - max_pixclk_khz = max(max_pixclk_khz, t->pixclk_khz); + if (pixclk_khz && (t->hact + hbl)) { + min_hor_freq_hz = min(min_hor_freq_hz, (pixclk_khz * 1000) / (t->hact + hbl)); + max_hor_freq_hz = max(max_hor_freq_hz, (pixclk_khz * 1000) / (t->hact + hbl)); + max_pixclk_khz = max(max_pixclk_khz, pixclk_khz); } return ok; } diff --git a/edid-decode.h b/edid-decode.h index c26774a..b72b9eb 100644 --- a/edid-decode.h +++ b/edid-decode.h @@ -53,6 +53,7 @@ struct timings { bool even_vtotal; // special for VIC 39 bool no_pol_vsync; // digital composite signals have no vsync polarity unsigned hsize_mm, vsize_mm; + bool ycbcr420; // YCbCr 4:2:0 encoding }; struct edid_state { @@ -182,8 +183,8 @@ struct edid_state { void detailed_block(const unsigned char *x); void parse_base_block(const unsigned char *x); - void print_vic_index(const char *prefix, unsigned idx, const char *suffix); - void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420); + void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false); + void cta_svd(const unsigned char *x, unsigned n, bool for_ycbcr420); void cta_y420cmdb(const unsigned char *x, unsigned length); void cta_vfpdb(const unsigned char *x, unsigned length); void cta_hdmi_block(const unsigned char *x, unsigned length); diff --git a/parse-base-block.cpp b/parse-base-block.cpp index f842264..bd5ad37 100644 --- a/parse-base-block.cpp +++ b/parse-base-block.cpp @@ -982,6 +982,19 @@ void edid_state::detailed_display_range_limits(const unsigned char *x) range_class.c_str(), x[5] + v_min_offset, x[6] + v_max_offset, x[7] + h_min_offset, x[8] + h_max_offset); + + // For EDID 1.3 the horizontal frequency maxes out at 255 kHz. + // So to avoid false range-check warnings due to this limitation, + // just double the max_display_hor_freq_hz in this case. + if (edid_minor < 4 && x[8] == 0xff) + max_display_hor_freq_hz *= 2; + + // For EDID 1.3 the vertical frequency maxes out at 255 Hz. + // So to avoid false range-check warnings due to this limitation, + // just double the max_display_vert_freq_hz in this case. + if (edid_minor < 4 && x[6] == 0xff) + max_display_vert_freq_hz *= 2; + if (x[9]) { max_display_pixclk_khz = x[9] * 10000; printf(", max dotclock %d MHz\n", x[9] * 10); diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp index 2a2837b..8f4026d 100644 --- a/parse-cta-block.cpp +++ b/parse-cta-block.cpp @@ -342,7 +342,7 @@ static void cta_audio_block(const unsigned char *x, unsigned length) } } -void edid_state::cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420) +void edid_state::cta_svd(const unsigned char *x, unsigned n, bool for_ycbcr420) { unsigned i; @@ -387,7 +387,13 @@ void edid_state::cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420) sprintf(type, "VIC %3u", vic); const char *flags = native ? "native" : ""; - print_timings(" ", t, type, flags); + if (for_ycbcr420) { + struct timings tmp = *t; + tmp.ycbcr420 = true; + print_timings(" ", &tmp, type, flags); + } else { + print_timings(" ", t, type, flags); + } if (override_pref) { preferred_timings = *t; preferred_type = type; @@ -408,7 +414,7 @@ void edid_state::cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420) } } -void edid_state::print_vic_index(const char *prefix, unsigned idx, const char *suffix) +void edid_state::print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420) { if (!suffix) suffix = ""; @@ -419,11 +425,14 @@ void edid_state::print_vic_index(const char *prefix, unsigned idx, const char *s sprintf(buf, "VIC %3u", vic); - if (t) - print_timings(prefix, t, buf, suffix); - else + if (t) { + struct timings tmp = *t; + tmp.ycbcr420 = ycbcr420; + print_timings(prefix, &tmp, buf, suffix); + } else { printf("%sUnknown (%s%s%s)\n", prefix, buf, *suffix ? ", " : "", suffix); + } } else { // Should not happen! printf("%sSVD Index %u is out of range", prefix, idx + 1); @@ -457,7 +466,7 @@ void edid_state::cta_y420cmdb(const unsigned char *x, unsigned length) if (!(v & (1 << j))) continue; - print_vic_index(" ", i * 8 + j, ""); + print_vic_index(" ", i * 8 + j, "", true); max_idx = i * 8 + j; if (max_idx < preparsed_svds[0].size()) { unsigned vic = preparsed_svds[0][max_idx]; @@ -1682,7 +1691,7 @@ void edid_state::cta_ext_block(const unsigned char *x, unsigned length) case 0x06: cta_hdr_static_metadata_block(x + 1, length); return; case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return; case 0x0d: cta_vfpdb(x + 1, length); return; - case 0x0e: cta_svd(x + 1, length, 1); return; + case 0x0e: cta_svd(x + 1, length, true); return; case 0x0f: cta_y420cmdb(x + 1, length); return; case 0x12: cta_hdmi_audio_block(x + 1, length); return; case 0x13: cta_rcdb(x + 1, length); return; @@ -1725,7 +1734,7 @@ void edid_state::cta_block(const unsigned char *x) case 0x02: data_block = "Video Data Block"; printf(" %s:\n", data_block.c_str()); - cta_svd(x + 1, length, 0); + cta_svd(x + 1, length, false); break; case 0x03: oui = (x[3] << 16) + (x[2] << 8) + x[1]; |