[PATCH v2] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks

From: vishnu . saini

Date: Wed Jun 24 2026 - 04:41:02 EST


From: Ravi Agola <raviagol@xxxxxxxxxxxxxxxx>

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.

Add driver support to fetch up to 4 EDID blocks by re-triggering
EDID access after the first 2 blocks are read. For block 0 and 2,
set the EDID ready flag in 0xb028 so the bridge can expose the
corresponding EDID blocks, then retry the read until the expected
EDID is fetched.

Also reset the edid_read flag on HPD disconnect so that the next
connect event triggers a fresh EDID fetch.

Signed-off-by: Ravi Agola <raviagol@xxxxxxxxxxxxxxxx>
Signed-off-by: Vishnu Saini <vishnu.saini@xxxxxxxxxxxxxxxx>
---
Changes in v2:
- Removed memcpy and doing edid fetch everytime. Required an update in firmware as well for edid block0 reset.
- Verified patch with existing firmware V5.0.21, patch is not causing any regression if V5.0.21 firmware is used.
- Firmware V5.0.22 is required with this patch to support edid fetch on more than 2 edid block monitors.
- Link to v1: https://lore.kernel.org/r/20260517-lt9611usc_edid34_misc_next-v1-1-5e2fd8c6399b@xxxxxxxxxxxxxxxx
---
drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 74 +++++++++++++++++++++++++-----
1 file changed, 63 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 11aab07d88df..6c13d93996b1 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"

@@ -170,6 +170,9 @@ static void lt9611uxc_hpd_work(struct work_struct *work)
connected = lt9611uxc->hdmi_connected;
mutex_unlock(&lt9611uxc->ocm_lock);

+ if (!connected)
+ lt9611uxc->edid_read = false;
+
drm_bridge_hpd_notify(&lt9611uxc->bridge,
connected ?
connector_status_connected :
@@ -384,10 +387,35 @@ 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;
+ unsigned int edid_ready_flag = 0;
+ bool header_matched;
+ const u8 edid_header[8] = { 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00 };

if (len > EDID_BLOCK_SIZE)
return -EINVAL;
@@ -395,20 +423,44 @@ 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 == 0 || block == 2) {

- regmap_write(lt9611uxc->regmap, 0xb00b, 0x10);
+ lt9611uxc_lock(lt9611uxc);

- regmap_write(lt9611uxc->regmap, 0xb00a, block * EDID_BLOCK_SIZE);
+ edid_ready_flag = (block == 0) ? BIT(0) : BIT(1);

- ret = regmap_noinc_read(lt9611uxc->regmap, 0xb0b0, buf, len);
- if (ret)
- dev_err(lt9611uxc->dev, "edid read failed: %d\n", ret);
+ /*
+ * Set the EDID ready flag so that lt9611uxc can fetch correct EDID block
+ */
+ regmap_write(lt9611uxc->regmap, 0xb028, edid_ready_flag);

- lt9611uxc_unlock(lt9611uxc);
+ lt9611uxc_unlock(lt9611uxc);

- return 0;
-};
+ do {
+ msleep(100);
+ ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
+ if (ret)
+ break;
+ /*
+ * Compare first 8 bytes of EDID header for block 0 and block 2
+ * to confirm EDID read successfully
+ */
+ header_matched = (memcmp(edid_header, buf, 8) == 0);
+ if ((block == 0 && header_matched) ||
+ (block == 2 && !header_matched))
+ break;
+
+ } while (retry_cnt-- > 0);
+ } else {
+ ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
+
+ lt9611uxc_lock(lt9611uxc);
+ regmap_write(lt9611uxc->regmap, 0xb028, 0x00);
+ lt9611uxc_unlock(lt9611uxc);
+ }
+
+ return ret;
+}

static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *bridge,
struct drm_connector *connector)

---
base-commit: 4c26e162947f91aa78ba57dd4fddd38fc80e7d60
change-id: 20260517-lt9611usc_edid34_misc_next-b02592de0b25

Best regards,
--
Vishnu Saini <vishnu.saini@xxxxxxxxxxxxxxxx>