aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--edid-decode.cpp20
-rw-r--r--edid-decode.h5
-rw-r--r--parse-base-block.cpp13
-rw-r--r--parse-cta-block.cpp27
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];

Privacy Policy