Add an iterator abstraction for going through all the EDID blocks.

Signed-off-by: Jani Nikula <jani.nik...@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 46 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 6c188539493e..31d132fcd0ca 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3348,6 +3348,52 @@ add_detailed_modes(struct drm_connector *connector, 
struct edid *edid,
 #define EDID_CEA_YCRCB422      (1 << 4)
 #define EDID_CEA_VCDB_QS       (1 << 6)
 
+/*
+ * EDID base and extension block iterator.
+ *
+ * struct drm_edid_iter iter;
+ * const u8 *block;
+ *
+ * drm_edid_iter_begin(edid, &iter);
+ * drm_edid_iter_for_each(block, &iter) {
+ *         // do stuff with block
+ * }
+ * drm_edid_iter_end(&iter);
+ */
+struct drm_edid_iter {
+       const struct edid *edid;
+
+       /* Current block index. */
+       int index;
+};
+
+static void drm_edid_iter_begin(const struct edid *edid,
+                               struct drm_edid_iter *iter)
+{
+       memset(iter, 0, sizeof(*iter));
+
+       iter->edid = edid;
+}
+
+static const void *__drm_edid_iter_next(struct drm_edid_iter *iter)
+{
+       if (!iter->edid)
+               return NULL;
+
+       if (iter->index > drm_edid_extension_block_count(iter->edid))
+               return NULL;
+
+       return (const u8 *)iter->edid + EDID_LENGTH * iter->index++;
+}
+
+#define drm_edid_iter_for_each(__block, __iter)                        \
+       while (((__block) = __drm_edid_iter_next(__iter)))
+
+static void drm_edid_iter_end(struct drm_edid_iter *iter)
+{
+       memset(iter, 0, sizeof(*iter));
+}
+
 /*
  * Search EDID for CEA extension block.
  */
-- 
2.30.2

Reply via email to