edid: add edid_get_timing_validate() variant to filter out edid modes
[oweals/u-boot.git] / common / edid.c
index 19410aa4fcc52c3ff993dfe8d64a5b470d419c1b..f244d26e04be491f71cf912a9aba8c9b848c0a0f 100644 (file)
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2012 The Chromium OS Authors.
  *
  * (C) Copyright 2010
  * Petr Stetiar <ynezz@true.cz>
  *
- * SPDX-License-Identifier:    GPL-2.0+
- *
  * Contains stolen code from ddcprobe project which is:
  * Copyright (C) Nalin Dahyabhai <bigfun@pobox.com>
  */
@@ -148,8 +147,8 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info)
        /* check for end of data block */
        end = info->dtd_offset;
        if (end == 0)
-               end = 127;
-       if (end < 4 || end > 127)
+               end = sizeof(info->data);
+       if (end < 4 || end > sizeof(info->data))
                return false;
        end -= 4;
 
@@ -169,8 +168,12 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info)
        return false;
 }
 
-int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
-                   int *panel_bits_per_colourp)
+int edid_get_timing_validate(u8 *buf, int buf_size,
+                            struct display_timing *timing,
+                            int *panel_bits_per_colourp,
+                            bool (*mode_valid)(void *priv,
+                                       const struct display_timing *timing),
+                            void *mode_valid_priv)
 {
        struct edid1_info *edid = (struct edid1_info *)buf;
        bool timing_done;
@@ -194,7 +197,11 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
                desc = &edid->monitor_details.descriptor[i];
                if (desc->zero_flag_1 != 0) {
                        decode_timing((u8 *)desc, timing);
-                       timing_done = true;
+                       if (mode_valid)
+                               timing_done = mode_valid(mode_valid_priv,
+                                                        timing);
+                       else
+                               timing_done = true;
                        break;
                }
        }
@@ -226,6 +233,14 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
        return 0;
 }
 
+int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
+                   int *panel_bits_per_colourp)
+{
+       return edid_get_timing_validate(buf, buf_size, timing,
+                                       panel_bits_per_colourp, NULL, NULL);
+}
+
+
 /**
  * Snip the tailing whitespace/return of a string.
  *
@@ -295,7 +310,7 @@ static void edid_print_dtd(struct edid_monitor_descriptor *monitor,
 
                h_total = h_active + h_blanking;
                v_total = v_active + v_blanking;
-               if (v_total * h_total)
+               if (v_total > 0 && h_total > 0)
                        vfreq = pixclock / (v_total * h_total);
                else
                        vfreq = 1; /* Error case */