[PATCH] edid: investigate dtd from cea861 extension if necessary
Jerome Brunet
jbrunet at baylibre.com
Tue Nov 3 13:50:31 CET 2020
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 at libre.computer>
Tested-by: Da Xue <da at libre.computer>
Signed-off-by: Jerome Brunet <jbrunet at 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;
}
--
2.28.0
More information about the U-Boot
mailing list