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

vishnu.saini@oss.qualcomm.com posted 1 patch 1 week ago
drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 84 ++++++++++++++++++++++++++----
1 file changed, 73 insertions(+), 11 deletions(-)
[PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
Posted by vishnu.saini@oss.qualcomm.com 1 week ago
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(&lt9611uxc->ocm_lock);
 
+	if (!connected) {
+		lt9611uxc->edid_read = false;
+		drm_edid_free(lt9611uxc->edid_data);
+		lt9611uxc->edid_data = NULL;
+	}
+
 	drm_bridge_hpd_notify(&lt9611uxc->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>
Re: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
Posted by kernel test robot 1 week ago
Hi,

kernel test robot noticed the following build errors:

[auto build test ERROR on 4c26e162947f91aa78ba57dd4fddd38fc80e7d60]

url:    https://github.com/intel-lab-lkp/linux/commits/vishnu-saini-oss-qualcomm-com/drm-bridge-lt9611uxc-support-displays-with-up-to-4-EDID-blocks/20260518-021632
base:   4c26e162947f91aa78ba57dd4fddd38fc80e7d60
patch link:    https://lore.kernel.org/r/20260517-lt9611usc_edid34_misc_next-v1-1-5e2fd8c6399b%40oss.qualcomm.com
patch subject: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
config: i386-randconfig-014-20260518 (https://download.01.org/0day-ci/archive/20260518/202605180800.luZQCJZK-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260518/202605180800.luZQCJZK-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605180800.luZQCJZK-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/string.h:386,
                    from include/linux/bitmap.h:13,
                    from include/linux/cpumask.h:11,
                    from arch/x86/include/asm/paravirt.h:19,
                    from arch/x86/include/asm/irqflags.h:100,
                    from include/linux/irqflags.h:18,
                    from include/linux/spinlock.h:59,
                    from include/linux/mmzone.h:8,
                    from include/linux/gfp.h:7,
                    from include/linux/firmware.h:8,
                    from drivers/gpu/drm/bridge/lontium-lt9611uxc.c:7:
   In function 'memcmp',
       inlined from 'lt9611uxc_get_edid_block' at drivers/gpu/drm/bridge/lontium-lt9611uxc.c:454:23:
>> include/linux/fortify-string.h:719:25: error: call to '__read_overflow2' declared with attribute error: detected read beyond size of object (2nd parameter)
     719 |                         __read_overflow2();
         |                         ^~~~~~~~~~~~~~~~~~


vim +/__read_overflow2 +719 include/linux/fortify-string.h

a28a6e860c6cf23 Francis Laniel 2021-02-25  708  
92df138a8d663ce Kees Cook      2022-02-08  709  __FORTIFY_INLINE __diagnose_as(__builtin_memcmp, 1, 2, 3)
281d0c962752fb4 Kees Cook      2022-02-08  710  int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size)
a28a6e860c6cf23 Francis Laniel 2021-02-25  711  {
21a2c74b0a2a784 Kees Cook      2023-04-07  712  	const size_t p_size = __struct_size(p);
21a2c74b0a2a784 Kees Cook      2023-04-07  713  	const size_t q_size = __struct_size(q);
a28a6e860c6cf23 Francis Laniel 2021-02-25  714  
a28a6e860c6cf23 Francis Laniel 2021-02-25  715  	if (__builtin_constant_p(size)) {
fa35198f39571bb Kees Cook      2022-09-19  716  		if (__compiletime_lessthan(p_size, size))
a28a6e860c6cf23 Francis Laniel 2021-02-25  717  			__read_overflow();
fa35198f39571bb Kees Cook      2022-09-19  718  		if (__compiletime_lessthan(q_size, size))
a28a6e860c6cf23 Francis Laniel 2021-02-25 @719  			__read_overflow2();
a28a6e860c6cf23 Francis Laniel 2021-02-25  720  	}
3d965b33e40d973 Kees Cook      2023-04-07  721  	if (p_size < size)
3d965b33e40d973 Kees Cook      2023-04-07  722  		fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, p_size, size, INT_MIN);
3d965b33e40d973 Kees Cook      2023-04-07  723  	else if (q_size < size)
3d965b33e40d973 Kees Cook      2023-04-07  724  		fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, q_size, size, INT_MIN);
a28a6e860c6cf23 Francis Laniel 2021-02-25  725  	return __underlying_memcmp(p, q, size);
a28a6e860c6cf23 Francis Laniel 2021-02-25  726  }
a28a6e860c6cf23 Francis Laniel 2021-02-25  727  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
Posted by kernel test robot 1 week ago
Hi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 4c26e162947f91aa78ba57dd4fddd38fc80e7d60]

url:    https://github.com/intel-lab-lkp/linux/commits/vishnu-saini-oss-qualcomm-com/drm-bridge-lt9611uxc-support-displays-with-up-to-4-EDID-blocks/20260518-021632
base:   4c26e162947f91aa78ba57dd4fddd38fc80e7d60
patch link:    https://lore.kernel.org/r/20260517-lt9611usc_edid34_misc_next-v1-1-5e2fd8c6399b%40oss.qualcomm.com
patch subject: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
config: csky-randconfig-001-20260518 (https://download.01.org/0day-ci/archive/20260518/202605180850.uN2x73KR-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260518/202605180850.uN2x73KR-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605180850.uN2x73KR-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/bridge/lontium-lt9611uxc.c: In function 'lt9611uxc_get_edid_block':
>> drivers/gpu/drm/bridge/lontium-lt9611uxc.c:454:37: warning: 'memcmp' specified bound 8 exceeds source size 4 [-Wstringop-overread]
     454 |                 while (!ret && 0 == memcmp(&edid_header, &buf, 8) && retry_cnt-- > 0) {
         |                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/bridge/lontium-lt9611uxc.c:415:53: note: source object allocated here
     415 | static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
         |                                                 ~~~~^~~


vim +/memcmp +454 drivers/gpu/drm/bridge/lontium-lt9611uxc.c

   414	
   415	static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
   416	{
   417		struct lt9611uxc *lt9611uxc = data;
   418		int ret = 0;
   419		int retry_cnt = 10;
   420		int edid_ext_block;
   421		const u8 edid_header[8] = { 0x00, 0xFF, 0xFF, 0xFF,
   422					    0xFF, 0xFF, 0xFF, 0x00 };
   423	
   424		if (len > EDID_BLOCK_SIZE)
   425			return -EINVAL;
   426	
   427		if (block >= EDID_NUM_BLOCKS)
   428			return -EINVAL;
   429	
   430		if (block == 2) {
   431			lt9611uxc_lock(lt9611uxc);
   432	
   433			/* Read number of block available in EDID data */
   434			ret = regmap_read(lt9611uxc->regmap, 0xb02a, &edid_ext_block);
   435			if (ret) {
   436				dev_err(lt9611uxc->dev, "edid block read failed: %d\n", ret);
   437				lt9611uxc_unlock(lt9611uxc);
   438				return ret;
   439			}
   440	
   441			/* Reset EDID ready flag so that lt9611uxc can read 2nd and 3rd block */
   442			regmap_write(lt9611uxc->regmap, 0xb02a, (edid_ext_block & (~BIT(3))));
   443	
   444			lt9611uxc_unlock(lt9611uxc);
   445	
   446			msleep(100);
   447	
   448			ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
   449	
   450			/*
   451			 * Compare first 8 bytes of EDID header (0th block) and 2nd block to confirm
   452			 * that 2nd EDID block data is read successfully by lt9611uxc
   453			 */
 > 454			while (!ret && 0 == memcmp(&edid_header, &buf, 8) && retry_cnt-- > 0) {
   455				msleep(100);
   456				ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
   457			}
   458		} else {
   459			ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len);
   460		}
   461	
   462		return ret;
   463	};
   464	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
Posted by Dmitry Baryshkov 1 week ago
On Sun, May 17, 2026 at 11:44:49PM +0530, vishnu.saini@oss.qualcomm.com wrote:
> 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.

Won't this affect re-reading of the EDID? If so, we might need to reset
the flag at the block0 path too.

> 
> 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.

Separte commit, separate justification. Most of the drivers don't use
the cache, so, I'd say, most likely no.

> 
> 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(-)
> 
-- 
With best wishes
Dmitry
Re: [PATCH] drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks
Posted by Vishnu Saini 6 days, 16 hours ago
On Sun, May 17, 2026 at 11:58:55PM +0300, Dmitry Baryshkov wrote:
> On Sun, May 17, 2026 at 11:44:49PM +0530, vishnu.saini@oss.qualcomm.com wrote:
> > 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.
> 
> Won't this affect re-reading of the EDID? If so, we might need to reset
> the flag at the block0 path too.

Yes, edid will be invalid while reading again, that's why trying to cache it.
Correct edid received after HPD. Will try reset the flag at block0

> > 
> > 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.
> 
> Separte commit, separate justification. Most of the drivers don't use
> the cache, so, I'd say, most likely no.
If flag reset at block0 gives correct edid we don't have to cache it, just that
it will take few extra ms to load the edid data again.

Lontium also shared the updated firmware to load upto 4 block edid, will check with them
on upstreaming plan.
 
> > 
> > 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(-)
> > 
> -- 
> With best wishes
> Dmitry