dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Jani Nikula <jani.nikula@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: jani.nikula@intel.com
Subject: [Intel-gfx] [PATCH v2 06/20] drm/edid: add iterator for CTA data blocks
Date: Tue,  3 May 2022 12:23:51 +0300	[thread overview]
Message-ID: <37fdd2d9eabc73aaa9f95c56246dc47aea0e8e4e.1651569697.git.jani.nikula@intel.com> (raw)
In-Reply-To: <cover.1651569697.git.jani.nikula@intel.com>

Add an iterator for CTA Data Blocks across EDID CTA Extensions and
DisplayID CTA Data Blocks.

v2: Update references, note why we can trust displayid ranges (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 202 ++++++++++++++++++++++++++++++++++---
 1 file changed, 190 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 6d71b2b77639..da8f455b725e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4336,24 +4336,12 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
 	return modes;
 }
 
-static int
-cea_db_payload_len(const u8 *db)
-{
-	return db[0] & 0x1f;
-}
-
 static int
 cea_db_extended_tag(const u8 *db)
 {
 	return db[1];
 }
 
-static int
-cea_db_tag(const u8 *db)
-{
-	return db[0] >> 5;
-}
-
 static int
 cea_revision(const u8 *cea)
 {
@@ -4409,6 +4397,196 @@ cea_db_offsets(const u8 *cea, int *start, int *end)
 	return 0;
 }
 
+/*
+ * CTA Data Block iterator.
+ *
+ * Iterate through all CTA Data Blocks in both EDID CTA Extensions and DisplayID
+ * CTA Data Blocks.
+ *
+ * struct cea_db *db:
+ * struct cea_db_iter iter;
+ *
+ * cea_db_iter_edid_begin(edid, &iter);
+ * cea_db_iter_for_each(db, &iter) {
+ *         // do stuff with db
+ * }
+ * cea_db_iter_end(&iter);
+ */
+struct cea_db_iter {
+	struct drm_edid_iter edid_iter;
+	struct displayid_iter displayid_iter;
+
+	/* Current Data Block Collection. */
+	const u8 *collection;
+
+	/* Current Data Block index in current collection. */
+	int index;
+
+	/* End index in current collection. */
+	int end;
+};
+
+/* CTA-861-H section 7.4 CTA Data BLock Collection */
+struct cea_db {
+	u8 tag_length;
+	u8 data[];
+} __packed;
+
+static int cea_db_tag(const void *_db)
+{
+	/* FIXME: Transition to passing struct cea_db * everywhere. */
+	const struct cea_db *db = _db;
+
+	return db->tag_length >> 5;
+}
+
+static int cea_db_payload_len(const void *_db)
+{
+	/* FIXME: Transition to passing struct cea_db * everywhere. */
+	const struct cea_db *db = _db;
+
+	return db->tag_length & 0x1f;
+}
+
+static const void *cea_db_data(const struct cea_db *db)
+{
+	return db->data;
+}
+
+static void cea_db_iter_edid_begin(const struct edid *edid, struct cea_db_iter *iter)
+{
+	memset(iter, 0, sizeof(*iter));
+
+	drm_edid_iter_begin(edid, &iter->edid_iter);
+	displayid_iter_edid_begin(edid, &iter->displayid_iter);
+}
+
+static const struct cea_db *
+__cea_db_iter_current_block(const struct cea_db_iter *iter)
+{
+	const struct cea_db *db;
+
+	if (!iter->collection)
+		return NULL;
+
+	db = (const struct cea_db *)&iter->collection[iter->index];
+
+	if (iter->index + sizeof(*db) <= iter->end &&
+	    iter->index + sizeof(*db) + cea_db_payload_len(db) <= iter->end)
+		return db;
+
+	return NULL;
+}
+
+/*
+ * References:
+ * - VESA E-EDID v1.4
+ * - CTA-861-H section 7.3.3 CTA Extension Version 3
+ */
+static const void *__cea_db_iter_edid_next(struct cea_db_iter *iter)
+{
+	const u8 *ext;
+
+	drm_edid_iter_for_each(ext, &iter->edid_iter) {
+		/* Only support CTA Extension revision 3+ */
+		if (ext[0] != CEA_EXT || cea_revision(ext) < 3)
+			continue;
+
+		iter->index = 4;
+		iter->end = ext[2];
+		if (iter->end == 0)
+			iter->end = 127;
+		if (iter->end < 4 || iter->end > 127)
+			continue;
+
+		return ext;
+	}
+
+	return NULL;
+}
+
+/*
+ * References:
+ * - DisplayID v1.3 Appendix C: CEA Data Block within a DisplayID Data Block
+ * - DisplayID v2.0 section 4.10 CTA DisplayID Data Block
+ *
+ * Note that the above do not specify any connection between DisplayID Data
+ * Block revision and CTA Extension versions.
+ */
+static const void *__cea_db_iter_displayid_next(struct cea_db_iter *iter)
+{
+	const struct displayid_block *block;
+
+	displayid_iter_for_each(block, &iter->displayid_iter) {
+		if (block->tag != DATA_BLOCK_CTA)
+			continue;
+
+		/*
+		 * The displayid iterator has already verified the block bounds
+		 * in displayid_iter_block().
+		 */
+		iter->index = sizeof(*block);
+		iter->end = iter->index + block->num_bytes;
+
+		return block;
+	}
+
+	return NULL;
+}
+
+static const struct cea_db *__cea_db_iter_next(struct cea_db_iter *iter)
+{
+	const struct cea_db *db;
+
+	if (iter->collection) {
+		/* Current collection should always be valid. */
+		db = __cea_db_iter_current_block(iter);
+		if (WARN_ON(!db)) {
+			iter->collection = NULL;
+			return NULL;
+		}
+
+		/* Next block in CTA Data Block Collection */
+		iter->index += sizeof(*db) + cea_db_payload_len(db);
+
+		db = __cea_db_iter_current_block(iter);
+		if (db)
+			return db;
+	}
+
+	for (;;) {
+		/*
+		 * Find the next CTA Data Block Collection. First iterate all
+		 * the EDID CTA Extensions, then all the DisplayID CTA blocks.
+		 *
+		 * Per DisplayID v1.3 Appendix B: DisplayID as an EDID
+		 * Extension, it's recommended that DisplayID extensions are
+		 * exposed after all of the CTA Extensions.
+		 */
+		iter->collection = __cea_db_iter_edid_next(iter);
+		if (!iter->collection)
+			iter->collection = __cea_db_iter_displayid_next(iter);
+
+		if (!iter->collection)
+			return NULL;
+
+		db = __cea_db_iter_current_block(iter);
+		if (db)
+			return db;
+	}
+}
+
+#define cea_db_iter_for_each(__db, __iter) \
+	while (((__db) = __cea_db_iter_next(__iter)))
+
+static void cea_db_iter_end(struct cea_db_iter *iter)
+{
+	displayid_iter_end(&iter->displayid_iter);
+	drm_edid_iter_end(&iter->edid_iter);
+
+	memset(iter, 0, sizeof(*iter));
+}
+
 static bool cea_db_is_hdmi_vsdb(const u8 *db)
 {
 	if (cea_db_tag(db) != CTA_DB_VENDOR)
-- 
2.30.2


  parent reply	other threads:[~2022-05-04  8:02 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-03  9:23 [PATCH v2 00/20] drm/edid: CEA data block iterators, and more Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 01/20] drm/edid: reset display info in drm_add_edid_modes() for NULL edid Jani Nikula
2022-05-03  9:23 ` [PATCH v2 02/20] drm/edid: check for HF-SCDB block Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 03/20] drm/edid: rename HDMI Forum VSDB to SCDS Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 04/20] drm/edid: clean up CTA data block tag definitions Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 05/20] drm/edid: add iterator for EDID base and extension blocks Jani Nikula
2022-05-03  9:23 ` Jani Nikula [this message]
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 07/20] drm/edid: clean up cea_db_is_*() functions Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 08/20] drm/edid: convert add_cea_modes() to use cea db iter Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 09/20] drm/edid: convert drm_edid_to_speaker_allocation() " Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 10/20] drm/edid: convert drm_edid_to_sad() " Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 11/20] drm/edid: convert drm_detect_hdmi_monitor() " Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 12/20] drm/edid: convert drm_detect_monitor_audio() " Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 13/20] drm/edid: convert drm_parse_cea_ext() " Jani Nikula
2022-05-03  9:23 ` [Intel-gfx] [PATCH v2 14/20] drm/edid: convert drm_edid_to_eld() " Jani Nikula
2022-05-03  9:24 ` [Intel-gfx] [PATCH v2 15/20] drm/edid: sunset the old unused cea data block iterators Jani Nikula
2022-05-03  9:24 ` [Intel-gfx] [PATCH v2 16/20] drm/edid: restore some type safety to cea_db_*() functions Jani Nikula
2022-05-03  9:24 ` [Intel-gfx] [PATCH v2 17/20] drm/edid: detect basic audio in all CEA extensions Jani Nikula
2022-05-03  9:24 ` [Intel-gfx] [PATCH v2 18/20] drm/edid: detect color formats and CTA revision in all CTA extensions Jani Nikula
     [not found]   ` <20220505105242.1198521-1-jani.nikula@intel.com>
2022-05-05 14:32     ` [PATCH v3] " Ville Syrjälä
2022-05-03  9:24 ` [PATCH v2 19/20] drm/edid: skip CTA extension scan in drm_edid_to_eld() just for CTA rev Jani Nikula
2022-05-03  9:24 ` [PATCH v2 20/20] drm/edid: sunset drm_find_cea_extension() Jani Nikula
2022-05-04  8:10 ` [PATCH v2 00/20] drm/edid: CEA data block iterators, and more Jani Nikula
2022-05-04 22:30 ` Ville Syrjälä
2022-05-05 17:40   ` Jani Nikula

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=37fdd2d9eabc73aaa9f95c56246dc47aea0e8e4e.1651569697.git.jani.nikula@intel.com \
    --to=jani.nikula@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox