[PATCH] edid: investigate dtd from cea861 extension if necessary

If no valid detailed timing can be found in the edid base block, check the detailed timing provided in the cea861 extension block, if any.
Reported-by: Da Xue da@libre.computer Tested-by: Da Xue da@libre.computer Signed-off-by: Jerome Brunet jbrunet@baylibre.com --- common/edid.c | 72 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 23 deletions(-)
diff --git a/common/edid.c b/common/edid.c index 553ab8fd01a1..7dd0c924c24a 100644 --- a/common/edid.c +++ b/common/edid.c @@ -169,6 +169,33 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info) return false; }
+bool edid_get_dtd_timing_validate(struct edid_monitor_descriptor *desc, + unsigned int dtd_count, + struct display_timing *timing, + bool (*mode_valid)(void *priv, + const struct display_timing *timing), + void *mode_valid_priv) +{ + bool timing_done = false; + int i; + + for (i = 0; i < dtd_count; i++, desc++) { + if (desc->zero_flag_1 != 0) { + decode_timing((u8 *)desc, timing); + if (mode_valid) + timing_done = mode_valid(mode_valid_priv, + timing); + else + timing_done = true; + + if (timing_done) + break; + } + } + + return timing_done; +} + int edid_get_timing_validate(u8 *buf, int buf_size, struct display_timing *timing, int *panel_bits_per_colourp, @@ -177,8 +204,9 @@ int edid_get_timing_validate(u8 *buf, int buf_size, void *mode_valid_priv) { struct edid1_info *edid = (struct edid1_info *)buf; + struct edid_cea861_info *info = NULL; + struct edid_monitor_descriptor *desc; bool timing_done; - int i;
if (buf_size < sizeof(*edid) || edid_check_info(edid)) { debug("%s: Invalid buffer\n", __func__); @@ -190,24 +218,27 @@ int edid_get_timing_validate(u8 *buf, int buf_size, return -ENOENT; }
- /* Look for detailed timing */ - timing_done = false; - for (i = 0; i < 4; i++) { - struct edid_monitor_descriptor *desc; + desc = edid->monitor_details.descriptor; + timing_done = edid_get_dtd_timing_validate(desc, 4, timing, + mode_valid, mode_valid_priv);
- desc = &edid->monitor_details.descriptor[i]; - if (desc->zero_flag_1 != 0) { - decode_timing((u8 *)desc, timing); - if (mode_valid) - timing_done = mode_valid(mode_valid_priv, - timing); - else - timing_done = true; + if (edid->extension_flag && (buf_size >= EDID_EXT_SIZE)) { + info = (struct edid_cea861_info *)(buf + sizeof(*edid));
- if (timing_done) - break; - } + if (info->extension_tag != EDID_CEA861_EXTENSION_TAG) + info = NULL; + } + + /* Check CEA861 info block for timing if don't have one yet */ + if (info && !timing_done && info->dtd_offset) { + unsigned int dtd_count = EDID_CEA861_DTD_COUNT(*info); + + desc = (struct edid_monitor_descriptor *)((u8 *)info + + info->dtd_offset); + timing_done = edid_get_dtd_timing_validate(desc, dtd_count, timing, + mode_valid, mode_valid_priv); } + if (!timing_done) return -EINVAL;
@@ -225,13 +256,8 @@ int edid_get_timing_validate(u8 *buf, int buf_size, }
timing->hdmi_monitor = false; - if (edid->extension_flag && (buf_size >= EDID_EXT_SIZE)) { - struct edid_cea861_info *info = - (struct edid_cea861_info *)(buf + sizeof(*edid)); - - if (info->extension_tag == EDID_CEA861_EXTENSION_TAG) - timing->hdmi_monitor = cea_is_hdmi_vsdb_present(info); - } + if (info) + timing->hdmi_monitor = cea_is_hdmi_vsdb_present(info);
return 0; }
participants (1)
-
Jerome Brunet