linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: <Ching-shih.Li@amd.com>
To: <maarten.lankhorst@linux.intel.com>, <mripard@kernel.org>,
	<sean@poorly.run>, <airlied@linux.ie>, <daniel@ffwll.ch>,
	<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>
Cc: Louis Li <Ching-Shih.Li@amd.com>,
	"mika . hsu" <mika.hsu@quanta.corp-partner.google.com>
Subject: [PATCH] gpu/drm: Parse all ext. blocks in EDID
Date: Fri, 29 Jan 2021 14:33:53 +0800	[thread overview]
Message-ID: <20210129063353.95852-1-Ching-shih.Li@amd.com> (raw)

From: Louis Li <Ching-Shih.Li@amd.com>

[Why] EDID parser cannot correctly parse EDID which includes
multiple same extension blocks (e.g. two same ext. blocks: <Tag=0x02: CTA
 861>, are included in EDID defined in test case HF1-66, HDMI 2.0 CTS),
since it only parse the first target ext. block only. This causes CTS fail.

[How]
Original parser searches ext. block from HEAD of EDID,
and always return the first target ext. block.
Solution is to find all ext. blocks and pass start address
of each ext. block to parser to handle.

By this change, no matter how ext. block is placed in EDID, all
target ext. blocks are handled.

Tested-by: mika.hsu <mika.hsu@quanta.corp-partner.google.com>
Signed-off-by: Louis Li <Ching-Shih.Li@amd.com>
---
 drivers/gpu/drm/drm_edid.c | 52 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 14c6a4bb32ea..adcb04516b41 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4160,9 +4160,8 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
 }
 
 static int
-add_cea_modes(struct drm_connector *connector, struct edid *edid)
+handle_cea_modes(struct drm_connector *connector, const u8 *cea)
 {
-	const u8 *cea = drm_find_cea_extension(edid);
 	const u8 *db, *hdmi = NULL, *video = NULL;
 	u8 dbl, hdmi_len, video_len = 0;
 	int modes = 0;
@@ -4206,6 +4205,55 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
 	return modes;
 }
 
+static int
+add_cea_modes(struct drm_connector *connector, struct edid *edid)
+{
+	const u8 *cea = NULL;
+	u8 *edid_ext = NULL;
+	int modes = 0;
+	int block_index = 0;
+
+	/*
+	 * Based on HDMI(2.x) CTS: HF1-66 (Iter 06), two blocks with same
+	 * tag (Tag = 0x02: CTA 861) are included in EDID. Ori. solution
+	 * checks for all additional blocks, BUT it always checks from
+	 * HEAD. Result is only 1st CTA 861 can be found and checked.
+	 * Therefore, any following CTA 861 block is never found
+	 * to handle. The modified method is to check each additional
+	 * block by pointing to the start address of that block, instead
+	 * of finding from HEAD of EDID.
+	 *
+	 * TODO: EDID parser may need re-designed, since ori. parser can't
+	 * correctly parse multiple same ext. blocks (Tag = 0x02 in this
+	 * case), since it finds and parse the 1st target ext. block only.
+	 * 1. Ori. method is not flexible to work with EDID like HF1-66.
+	 * 2. Ori. method is not efficient: a block may be checked many times.
+	 * 3. Ori. method does not support new features, e.g. Ext. BLK MAP.
+	 * etc...
+	 */
+	for (block_index = 0; block_index < edid->extensions; block_index++) {
+		edid_ext = (((u8 *)edid) + (EDID_LENGTH * (block_index + 1)));
+
+		if (edid_ext[0] == CEA_EXT) {
+			cea = ((const u8 *)edid_ext);
+			modes += handle_cea_modes(connector, cea);
+		}
+	}
+
+	/*
+	 * If no Video Data extension block, go check DisplayID block,
+	 * because CEA block may be embedded in DisplayID block.
+	 */
+	if (!cea) {
+		cea = drm_find_cea_extension(edid);
+
+		if (cea)
+			modes += handle_cea_modes(connector, cea);
+	}
+
+	return modes;
+}
+
 static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
 {
 	const struct drm_display_mode *cea_mode;
-- 
2.25.1


                 reply	other threads:[~2021-01-29  6:38 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20210129063353.95852-1-Ching-shih.Li@amd.com \
    --to=ching-shih.li@amd.com \
    --cc=airlied@linux.ie \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mika.hsu@quanta.corp-partner.google.com \
    --cc=mripard@kernel.org \
    --cc=sean@poorly.run \
    /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;
as well as URLs for NNTP newsgroup(s).