[PATCH RFC 6/9] drm/bridge: tc358762: read back ID register

From: Andreas Kemnade

Date: Tue Sep 22 2026 - 02:19:07 EST


to check if reading works and in preparation for the PLL setup, read back
the ID register value. Also this produces better errors if chip is not
connected. In the Epson Moverio BT200, the DSI busses are on a (probably
not hot-) detachable cable.

Signed-off-by: Andreas Kemnade <andreas@xxxxxxxxxxxx>
---
drivers/gpu/drm/bridge/tc358762.c | 40 +++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 8024e49e2868..1bea89fb03a8 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -50,6 +50,8 @@
#define DSI_LANEENABLE_L0EN BIT(1)
#define DSI_LANEENABLE_L1EN BIT(2)

+#define RDPKTLN 0x0410 /* Packet length */
+
/* LCDC/DPI Registers */
#define LCDCTRL 0x0420 /* Video Path Control */
#define LCDCTRL_MSF BIT(0) /* Magic square in RGB666 */
@@ -97,6 +99,8 @@
#define SYSCTRL_PCLKDIV_DIV_2 2
#define SYSCTRL_PCLKDIV_DIV_3 4

+#define IDREG 0x04A0 /* Chip and Revision ID */
+
#define LPX_PERIOD 3

struct tc358762 {
@@ -119,6 +123,27 @@ static int tc358762_clear_error(struct tc358762 *ctx)
return ret;
}

+static int tc358762_read(struct tc358762 *ctx, u16 addr, u32 *val)
+{
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ ssize_t ret;
+ u8 addr_buf[2];
+ u8 buf[4];
+
+ put_unaligned_le16(addr, addr_buf);
+
+ ret = mipi_dsi_generic_read(dsi, addr_buf, 2, buf, sizeof(buf));
+ if (ret < 0) {
+ dev_err(ctx->dev, "gen read failed: %d\n", ret);
+ return ret;
+ }
+ dev_dbg(ctx->dev, "read return %02x %02x %02x %02x\n",
+ buf[0], buf[1], buf[2], buf[3]);
+
+ *val = get_unaligned_le32(buf);
+ return ret;
+}
+
static void tc358762_write(struct tc358762 *ctx, u16 addr, u32 val)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -182,6 +207,7 @@ static void tc358762_pre_enable(struct drm_bridge *bridge,
struct drm_display_mode *mode;
u32 lcdctrl;
int ret;
+ u32 id;

ret = regulator_enable(ctx->regulator);
if (ret < 0)
@@ -205,6 +231,8 @@ static void tc358762_pre_enable(struct drm_bridge *bridge,
*/
tc358762_write(ctx, LCDCTRL, 0);

+ tc358762_write(ctx, RDPKTLN, 3);
+
tc358762_write(ctx, SYSCTRL,
FIELD_PREP(SYSCTRL_DPIDATA_IO_MASK, SYSCTRL_DPIDATA_IO_4MA) |
FIELD_PREP(SYSCTRL_DPISTB_IO_MASK, SYSCTRL_DPISTB_IO_4MA) |
@@ -283,6 +311,18 @@ static void tc358762_pre_enable(struct drm_bridge *bridge,
if (ret < 0)
dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);

+ /*
+ * This generates an ack with error if the device is reinitialized
+ * without reset, ignore the error here, the second read should be
+ * successful.
+ */
+ tc358762_read(ctx, IDREG, &id);
+ ret = tc358762_read(ctx, IDREG, &id);
+ if (ret < 0)
+ dev_err(ctx->dev, "read id failed (%d)\n", ret);
+ else if (id != 0x6200)
+ dev_info(ctx->dev, "unknown chip with id %x\n", id);
+
ctx->pre_enabled = true;
}


--
2.47.3