From: vishnu.saini@oss.qualcomm.com
To: Andrzej Hajda <andrzej.hajda@intel.com>,
Neil Armstrong <neil.armstrong@linaro.org>,
Robert Foss <rfoss@kernel.org>,
Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
Jonas Karlman <jonas@kwiboo.se>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Luca Ceresoli <luca.ceresoli@bootlin.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
prahlad.valluru@oss.qualcomm.com,
Ravi Agola <raviagol@qti.qualcomm.com>,
Vishnu Saini <vishnu.saini@oss.qualcomm.com>
Subject: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
Date: Sun, 17 May 2026 23:44:49 +0530 [thread overview]
Message-ID: <20260517-lt9611usc_edid34_misc_next-v1-1-5e2fd8c6399b@oss.qualcomm.com> (raw)
From: Ravi Agola <raviagol@qti.qualcomm.com>
The LT9611UXC bridge can fetch only 2 EDID blocks at a time, which
previously limited EDID reading to 2 blocks and prevented support
for displays exposing more than 2 EDID blocks.
Extend the driver to support up to 4 EDID blocks by re-triggering
EDID access after the first 2 blocks are read. For block 2, clear
the EDID ready flag in 0xb02a so the bridge can expose the remaining
blocks, then retry the read until the expected EDID is returned.
Also cache the full EDID blob in the driver and reuse it until the
next HPD disconnect event, so repeated EDID reads do not re-query
the bridge.
Signed-off-by: Ravi Agola <raviagol@qti.qualcomm.com>
Signed-off-by: Vishnu Saini <vishnu.saini@oss.qualcomm.com>
---
drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 84 ++++++++++++++++++++++++++----
1 file changed, 73 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 11aab07d88df..b5a9f62b9fe3 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -28,7 +28,7 @@
#include <drm/display/drm_hdmi_audio_helper.h>
#define EDID_BLOCK_SIZE 128
-#define EDID_NUM_BLOCKS 2
+#define EDID_NUM_BLOCKS 4
#define FW_FILE "lt9611uxc_fw.bin"
@@ -61,6 +61,8 @@ struct lt9611uxc {
/* can be accessed from different threads, so protect this with ocm_lock */
bool hdmi_connected;
uint8_t fw_version;
+
+ const struct drm_edid *edid_data;
};
#define LT9611_PAGE_CONTROL 0xff
@@ -170,6 +172,12 @@ static void lt9611uxc_hpd_work(struct work_struct *work)
connected = lt9611uxc->hdmi_connected;
mutex_unlock(<9611uxc->ocm_lock);
+ if (!connected) {
+ lt9611uxc->edid_read = false;
+ drm_edid_free(lt9611uxc->edid_data);
+ lt9611uxc->edid_data = NULL;
+ }
+
drm_bridge_hpd_notify(<9611uxc->bridge,
connected ?
connector_status_connected :
@@ -384,10 +392,34 @@ static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc)
msecs_to_jiffies(500));
}
+static int lt9611uxc_read_edid_block(struct lt9611uxc *lt9611uxc, unsigned int block,
+ u8 *buf, size_t len)
+{
+ int ret;
+
+ lt9611uxc_lock(lt9611uxc);
+
+ regmap_write(lt9611uxc->regmap, 0xb00a, (block%2) * EDID_BLOCK_SIZE);
+
+ ret = regmap_noinc_read(lt9611uxc->regmap, 0xb0b0, buf, len);
+ if (ret) {
+ dev_err(lt9611uxc->dev, "edid block %d read failed: %d\n", block, ret);
+ lt9611uxc_unlock(lt9611uxc);
+ return -EINVAL;
+ }
+ lt9611uxc_unlock(lt9611uxc);
+
+ return ret;
+}
+
static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
{
struct lt9611uxc *lt9611uxc = data;
- int ret;
+ int ret = 0;
+ int retry_cnt = 10;
+ int edid_ext_block;
+ const u8 edid_header[8] = { 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00 };
if (len > EDID_BLOCK_SIZE)
return -EINVAL;
@@ -395,19 +427,39 @@ static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, siz
if (block >= EDID_NUM_BLOCKS)
return -EINVAL;
- lt9611uxc_lock(lt9611uxc);
+ if (block == 2) {
+ lt9611uxc_lock(lt9611uxc);
- regmap_write(lt9611uxc->regmap, 0xb00b, 0x10);
+ /* Read number of block available in EDID data */
+ ret = regmap_read(lt9611uxc->regmap, 0xb02a, &edid_ext_block);
+ if (ret) {
+ dev_err(lt9611uxc->dev, "edid block read failed: %d\n", ret);
+ lt9611uxc_unlock(lt9611uxc);
+ return ret;
+ }
- regmap_write(lt9611uxc->regmap, 0xb00a, block * EDID_BLOCK_SIZE);
+ /* Reset EDID ready flag so that lt9611uxc can read 2nd and 3rd block */
+ regmap_write(lt9611uxc->regmap, 0xb02a, (edid_ext_block & (~BIT(3))));
- ret = regmap_noinc_read(lt9611uxc->regmap, 0xb0b0, buf, len);
- if (ret)
- dev_err(lt9611uxc->dev, "edid read failed: %d\n", ret);
+ lt9611uxc_unlock(lt9611uxc);
- lt9611uxc_unlock(lt9611uxc);
+ msleep(100);
- return 0;
+ ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
+
+ /*
+ * Compare first 8 bytes of EDID header (0th block) and 2nd block to confirm
+ * that 2nd EDID block data is read successfully by lt9611uxc
+ */
+ while (!ret && 0 == memcmp(&edid_header, &buf, 8) && retry_cnt-- > 0) {
+ msleep(100);
+ ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
+ }
+ } else {
+ ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
+ }
+
+ return ret;
};
static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *bridge,
@@ -425,7 +477,17 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid
return NULL;
}
- return drm_edid_read_custom(connector, lt9611uxc_get_edid_block, lt9611uxc);
+ /* If EDID is read once, provide same EDID data till next HPD event */
+ if (lt9611uxc->edid_data == NULL) {
+ lt9611uxc->edid_data = drm_edid_read_custom(connector, lt9611uxc_get_edid_block,
+ lt9611uxc);
+ }
+
+ /*
+ * Copy the EDID data and return the copied value which will be freed by DRM.
+ * The original EDID data is cached in the driver until the next HPD event.
+ */
+ return drm_edid_dup(lt9611uxc->edid_data);
}
static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge,
---
base-commit: 4c26e162947f91aa78ba57dd4fddd38fc80e7d60
change-id: 20260517-lt9611usc_edid34_misc_next-b02592de0b25
Best regards,
--
Vishnu Saini <vishnu.saini@oss.qualcomm.com>
next reply other threads:[~2026-05-17 18:15 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-17 18:14 vishnu.saini [this message]
2026-05-17 20:58 ` [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks Dmitry Baryshkov
2026-05-18 0:16 ` kernel test robot
2026-05-18 0:36 ` kernel test robot
2026-05-18 6:00 ` Claude review: " Claude Code Review Bot
2026-05-18 6:00 ` Claude Code Review Bot
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=20260517-lt9611usc_edid34_misc_next-v1-1-5e2fd8c6399b@oss.qualcomm.com \
--to=vishnu.saini@oss.qualcomm.com \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=airlied@gmail.com \
--cc=andrzej.hajda@intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jernej.skrabec@gmail.com \
--cc=jonas@kwiboo.se \
--cc=linux-kernel@vger.kernel.org \
--cc=luca.ceresoli@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=prahlad.valluru@oss.qualcomm.com \
--cc=raviagol@qti.qualcomm.com \
--cc=rfoss@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/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