A bit more context than the previous patch that was a bit alone. This series parses yet a bit more of the EDID: - The HDMI VICs in the HDMI vendor specific block (HDMI 1.4, 4k modes) - The CEA Video Capability Data Block
It also includes 2 EDIDs of TVs that have those bits.
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- edid-decode.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-)
diff --git a/edid-decode.c b/edid-decode.c index 9840db6..7515181 100644 --- a/edid-decode.c +++ b/edid-decode.c @@ -32,6 +32,8 @@ #include <time.h> #include <ctype.h>
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) + static int claims_one_point_oh = 0; static int claims_one_point_two = 0; static int claims_one_point_three = 0; @@ -569,14 +571,92 @@ cea_audio_block(unsigned char *x) } }
+static const char *edid_cea_modes[] = { + "640x480@60Hz", + "720x480@60Hz", + "720x480@60Hz", + "1280x720@60Hz", + "1920x1080i@60Hz", + "1440x480i@60Hz", + "1440x480i@60Hz", + "1440x240@60Hz", + "1440x240@60Hz", + "2880x480i@60Hz", + "2880x480i@60Hz" + "2880x240@60Hz", + "2880x240@60Hz", + "1440x480@60Hz", + "1440x480@60Hz", + "1920x1080@60Hz", + "720x576@50Hz", + "720x576@50Hz", + "1280x720@50Hz", + "1920x1080i@50Hz", + "1440x576i@50Hz", + "1440x576i@50Hz", + "1440x288@50Hz", + "1440x288@50Hz", + "2880x576i@50Hz", + "2880x576i@50Hz", + "2880x288@50Hz", + "2880x288@50Hz", + "1440x576@50Hz", + "1440x576@50Hz", + "1920x1080@50Hz", + "1920x1080@24Hz", + "1920x1080@25Hz", + "1920x1080@30Hz", + "2880x480@60Hz", + "2880x480@60Hz", + "2880x576@50Hz", + "2880x576@50Hz", + "1920x1080i@50Hz", + "1920x1080i@100Hz", + "1280x720@100Hz", + "720x576@100Hz", + "720x576@100Hz", + "1440x576@100Hz", + "1440x576@100Hz", + "1920x1080i@120Hz", + "1280x720@120Hz", + "720x480@120Hz", + "720x480@120Hz", + "1440x480i@120Hz", + "1440x480i@120Hz", + "720x576@200Hz", + "720x576@200Hz", + "1440x576i@200Hz", + "1440x576i@200Hz", + "720x480@240Hz", + "720x480@240Hz", + "1440x480i@240Hz", + "1440x480i@240Hz", + "1280x720@24Hz", + "1280x720@25Hz", + "1280x720@30Hz", + "1920x1080@120Hz", + "1920x1080@100Hz", +}; + static void cea_video_block(unsigned char *x) { int i; int length = x[0] & 0x1f;
- for (i = 1; i < length; i++) - printf(" VIC %02d %s\n", x[i] & 0x7f, x[i] & 0x80 ? "(native)" : ""); + for (i = 1; i < length; i++) { + unsigned char vic = x[i] & 0x7f; + unsigned char native = x[i] & 0x80; + const char *mode; + + vic--; + if (vic < ARRAY_SIZE(edid_cea_modes)) + mode = edid_cea_modes[vic]; + else + mode = "Unknown mode"; + + printf(" VIC %02d %s %s\n", vic, mode, native ? "(native)" : ""); + } }
static void
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- data/skyworth-50e780u-hdmi | Bin 0 -> 256 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/skyworth-50e780u-hdmi
diff --git a/data/skyworth-50e780u-hdmi b/data/skyworth-50e780u-hdmi new file mode 100644 index 0000000000000000000000000000000000000000..b618a6ff5efbbe15141183266d961ba2c48dfd0c GIT binary patch literal 256 zcmZSh4+adr<%|rB3=9l1VvNiUHcAy-yeAigyU$P;^6=UJo`De^$TAcKUXWAB(+Fia z(x=G4Ajc@%AW<kIrVyc{3K5wHH0%#UaCT*Reo;w=La2ue7f|FcgP{+903QRF0vIrE zWMbAV@oo{2XB8G<WD;Z(RpYE@7Oa<O2D&AenTNrEVTX-=LjofcGoviSo*<x=J2XNa z;8tEJ0$M4cquKx#nb*U0p-bU`u7H5uGzMXivm}5b6BHZ_6?hy%p&~#>AOR)-?WZ{b
literal 0 HcmV?d00001
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- edid-decode.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/edid-decode.c b/edid-decode.c index 7515181..55e48a7 100644 --- a/edid-decode.c +++ b/edid-decode.c @@ -705,7 +705,7 @@ cea_hdmi_block(unsigned char *x) if (x[8] & 0x20) { int mask = 0, formats = 0; - int len_xx, len_3d; + int len_vic, len_3d; printf(" Extended HDMI video details:\n"); if (x[9 + b] & 0x80) printf(" 3D present\n"); @@ -730,14 +730,17 @@ cea_hdmi_block(unsigned char *x) printf(" Base EDID image size is in units of 5cm\n"); break; } - len_xx = (x[10 + b] & 0xe0) >> 5; + len_vic = (x[10 + b] & 0xe0) >> 5; len_3d = (x[10 + b] & 0x1f) >> 0; b += 2;
- if (len_xx) { - printf(" Skipping %d bytes that HDMI refuses to publicly" - " document\n", len_xx); - b += len_xx; + if (len_vic) { + int i; + + for (i = 0; i < len_vic; i++) + printf(" HDMI VIC %d\n", x[9 + b + i]); + + b += len_vic; }
if (len_3d) {
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- edid-decode.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/edid-decode.c b/edid-decode.c index 55e48a7..5061228 100644 --- a/edid-decode.c +++ b/edid-decode.c @@ -659,6 +659,13 @@ cea_video_block(unsigned char *x) } }
+static const char *edid_cea_hdmi_modes[] = { + "3840x2160@30Hz", + "3840x2160@25Hz", + "3840x2160@24Hz", + "4096x2160@24Hz", +}; + static void cea_hdmi_block(unsigned char *x) { @@ -737,8 +744,18 @@ cea_hdmi_block(unsigned char *x) if (len_vic) { int i;
- for (i = 0; i < len_vic; i++) - printf(" HDMI VIC %d\n", x[9 + b + i]); + for (i = 0; i < len_vic; i++) { + unsigned char vic = x[9 + b + i]; + const char *mode; + + vic--; + if (vic < ARRAY_SIZE(edid_cea_hdmi_modes)) + mode = edid_cea_hdmi_modes[vic]; + else + mode = "Unknown mode"; + + printf(" HDMI VIC %d %s\n", vic, mode); + }
b += len_vic; }
--- data/samsung-UE40D8000YU-hmdi | Bin 0 -> 256 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/samsung-UE40D8000YU-hmdi
diff --git a/data/samsung-UE40D8000YU-hmdi b/data/samsung-UE40D8000YU-hmdi new file mode 100644 index 0000000000000000000000000000000000000000..ba87cb02837173ede00d01206808dd4705eff699 GIT binary patch literal 256 zcmZSh4+acAx<}a=85kJ!L>QSHB8@7z-c4K_;xki?KOki9`-VdQMutX*#)hd3Q~5VD ztaM<qYLF<j&~=E=ab;K#1=J>&rWmjxkU`qOp}-6(0u=qrAmJ?)D9*s800uyjKMcW+ zzQLh>?hqly2qtEukKPmHS%g_dn1vJ+m6SQz*_(k5dBni~n3b8ah?$4MfnkTP!UYaS z2X=dhfC&qLc3&t0+AW~t+5oYeQI=s(&;>b#9U7qyFcF{{88HO`9aV^$c|g0dferx8 CDLnxI
literal 0 HcmV?d00001
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- edid-decode.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-)
diff --git a/edid-decode.c b/edid-decode.c index 5061228..7aed3c6 100644 --- a/edid-decode.c +++ b/edid-decode.c @@ -32,8 +32,6 @@ #include <time.h> #include <ctype.h>
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) - static int claims_one_point_oh = 0; static int claims_one_point_two = 0; static int claims_one_point_three = 0; @@ -65,6 +63,73 @@ static int warning_zero_preferred_refresh = 0;
static int conformant = 1;
+struct value { + int value; + const char *description; +}; + +struct field { + const char *name; + int start, end; + struct value *values; + int n_values; +}; + +#define DEFINE_FIELD(n, var, s, e, ...) \ + static struct value var##_values[] = { \ + __VA_ARGS__ \ + }; \ + static struct field var = { \ + .name = n, \ + .start = s, \ + .end = e, \ + .values = var##_values, \ + .n_values = ARRAY_SIZE(var##_values), \ + } + +static void +decode_value(struct field *field, int val, const char *prefix) +{ + struct value *v; + int i; + + for (i = 0; i < field->n_values; i++) { + v = &field->values[i]; + + if (v->value == val) + break; + } + + if (i == field->n_values) { + printf("%s%s: %d\n", prefix, field->name, val); + return; + } + + printf("%s%s: %s (%d)\n", prefix, field->name, v->description, val); +} + +static void +_decode(struct field **fields, int n_fields, int data, const char *prefix) +{ + int i; + + for (i = 0; i < n_fields; i++) { + struct field *f = fields[i]; + int field_length = f->end - f->start + 1; + int val; + + if (field_length == 32) + val = data; + else + val = (data >> f->start) & ((1 << field_length) - 1); + + decode_value(f, val, prefix); + } +} + +#define decode(fields, data, prefix) \ + _decode(fields, ARRAY_SIZE(fields), data, prefix) + static char *manufacturer_name(unsigned char *x) { static char name[4];
v2: Fix rebase fail that removed a necessary hunk
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- edid-decode.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)
diff --git a/edid-decode.c b/edid-decode.c index 5061228..083ddd9 100644 --- a/edid-decode.c +++ b/edid-decode.c @@ -65,6 +65,73 @@ static int warning_zero_preferred_refresh = 0;
static int conformant = 1;
+struct value { + int value; + const char *description; +}; + +struct field { + const char *name; + int start, end; + struct value *values; + int n_values; +}; + +#define DEFINE_FIELD(n, var, s, e, ...) \ + static struct value var##_values[] = { \ + __VA_ARGS__ \ + }; \ + static struct field var = { \ + .name = n, \ + .start = s, \ + .end = e, \ + .values = var##_values, \ + .n_values = ARRAY_SIZE(var##_values), \ + } + +static void +decode_value(struct field *field, int val, const char *prefix) +{ + struct value *v; + int i; + + for (i = 0; i < field->n_values; i++) { + v = &field->values[i]; + + if (v->value == val) + break; + } + + if (i == field->n_values) { + printf("%s%s: %d\n", prefix, field->name, val); + return; + } + + printf("%s%s: %s (%d)\n", prefix, field->name, v->description, val); +} + +static void +_decode(struct field **fields, int n_fields, int data, const char *prefix) +{ + int i; + + for (i = 0; i < n_fields; i++) { + struct field *f = fields[i]; + int field_length = f->end - f->start + 1; + int val; + + if (field_length == 32) + val = data; + else + val = (data >> f->start) & ((1 << field_length) - 1); + + decode_value(f, val, prefix); + } +} + +#define decode(fields, data, prefix) \ + _decode(fields, ARRAY_SIZE(fields), data, prefix) + static char *manufacturer_name(unsigned char *x) { static char name[4];
Signed-off-by: Damien Lespiau damien.lespiau@intel.com --- edid-decode.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/edid-decode.c b/edid-decode.c index 7aed3c6..58297c9 100644 --- a/edid-decode.c +++ b/edid-decode.c @@ -861,6 +861,44 @@ cea_hdmi_block(unsigned char *x) } }
+DEFINE_FIELD("YCbCr quantization", YCbCr_quantization, 7, 7, + { 0, "No Data" }, + { 1, "Selectable (via AVI YQ)" }); +DEFINE_FIELD("RGB quantization", RGB_quantization, 6, 6, + { 0, "No Data" }, + { 1, "Selectable (via AVI Q)" }); +DEFINE_FIELD("PT scan behaviour", PT_scan, 4, 5, + { 0, "No Data" }, + { 1, "Always Overscannned" }, + { 2, "Always Underscanned" }, + { 3, "Support both over- and underscan" }); +DEFINE_FIELD("IT scan behaviour", IT_scan, 2, 3, + { 0, "IT video formats not supported" }, + { 1, "Always Overscannned" }, + { 2, "Always Underscanned" }, + { 3, "Support both over- and underscan" }); +DEFINE_FIELD("CE scan behaviour", CE_scan, 0, 1, + { 0, "CE video formats not supported" }, + { 1, "Always Overscannned" }, + { 2, "Always Underscanned" }, + { 3, "Support both over- and underscan" }); + +static struct field *vcdb_fields[] = { + &YCbCr_quantization, + &RGB_quantization, + &PT_scan, + &IT_scan, + &CE_scan, +}; + +static void +cea_vcdb(unsigned char *x) +{ + unsigned char d = x[2]; + + decode(vcdb_fields, d, " "); +} + static void cea_block(unsigned char *x) { @@ -895,6 +933,7 @@ cea_block(unsigned char *x) switch (x[1]) { case 0x00: printf("video capability data block\n"); + cea_vcdb(x); break; case 0x01: printf("vendor-specific video data block\n");
dri-devel@lists.freedesktop.org