* [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes
@ 2026-09-07 11:27 Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 01/13] drm/bridge: tc358762: Clean up register defines Tomi Valkeinen
` (13 more replies)
0 siblings, 14 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:27 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen,
Andreas Kemnade
While trying to get Raspberry Pi display v1.1 working on Beagleboard
platforms, I noticed various small issues with the tc358762 driver.
The series also contains a patch to fix the timings in the
powertip,ph800480t013-idf02 panel. The combination of tc358762 +
ph800480t013 is used in the Raspberry Pi display module, so it makes
sense to fix them together.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
Changes in v4:
- Rebased on latest upstream, fixing the minor compilation issues that it
brought
- Added R-b tags
- Link to v3: https://lore.kernel.org/r/20260513-tc358762-fixes-v3-0-6698b55008b9@ideasonboard.com
Changes in v3:
- Add missing #include <linux/bitfield.h>
- New patch: "drm/panel-simple: Fix powertip,ph800480t013-idf02 timings"
- Link to v2: https://lore.kernel.org/r/20260327-tc358762-fixes-v2-0-3589d3c45f4a@ideasonboard.com
Changes in v2:
- Always enable VTG. There should be no downside, and it fixes unstable
hsync
- Add four new patches at the end
- Extend the patch desc in "Drop SPICMR write" a bit
- Link to v1: https://lore.kernel.org/r/20260326-tc358762-fixes-v1-0-65f479227af5@ideasonboard.com
---
Tomi Valkeinen (13):
drm/bridge: tc358762: Clean up register defines
drm/bridge: tc358762: Improve SYSCTRL register defines
drm/bridge: tc358762: Improve LCDCTRL defines
drm/bridge: tc358762: Configure SYSCTRL first
drm/bridge: tc358762: Drop SPICMR write
drm/bridge: tc358762: Improve DPI enable handling
drm/bridge: tc358762: Update comment about the number of lanes
drm/bridge: tc358762: Support VTG
drm/bridge: tc358762: Fix sync polarities
drm/bridge: tc358762: Move tc358762_init() into tc358762_enable()
drm/bridge: tc358762: Drop drm_bridge_funcs.mode_set
drm/bridge: tc358762: Set DE_POL and DCLK_POL properly
drm/panel-simple: Fix powertip,ph800480t013-idf02 timings
drivers/gpu/drm/bridge/tc358762.c | 203 +++++++++++++++++++++++------------
drivers/gpu/drm/panel/panel-simple.c | 14 +--
2 files changed, 144 insertions(+), 73 deletions(-)
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20260326-tc358762-fixes-6f666500da9e
Best regards,
--
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 01/13] drm/bridge: tc358762: Clean up register defines
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
@ 2026-09-07 11:27 ` Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 02/13] drm/bridge: tc358762: Improve SYSCTRL " Tomi Valkeinen
` (12 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:27 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
Move the defines around and rename for clarity and consistency. No
functional change.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 6aa93b3274dd..dc20f253c7ad 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -28,17 +28,22 @@
/* PPI layer registers */
#define PPI_STARTPPI 0x0104 /* START control bit */
+#define PPI_STARTPPI_STARTPPI BIT(0)
+
#define PPI_LPTXTIMECNT 0x0114 /* LPTX timing signal */
#define PPI_D0S_ATMR 0x0144
#define PPI_D1S_ATMR 0x0148
#define PPI_D0S_CLRSIPOCOUNT 0x0164 /* Assertion timer for Lane 0 */
#define PPI_D1S_CLRSIPOCOUNT 0x0168 /* Assertion timer for Lane 1 */
-#define PPI_START_FUNCTION 1
/* DSI layer registers */
#define DSI_STARTDSI 0x0204 /* START control bit of DSI-TX */
+#define DSI_STARTDSI_STARTDSI BIT(0)
+
#define DSI_LANEENABLE 0x0210 /* Enables each lane */
-#define DSI_RX_START 1
+#define DSI_LANEENABLE_CLEN BIT(0)
+#define DSI_LANEENABLE_L0EN BIT(1)
+#define DSI_LANEENABLE_L1EN BIT(2)
/* LCDC/DPI Host Registers, based on guesswork that this matches TC358764 */
#define LCDCTRL 0x0420 /* Video Path Control */
@@ -59,14 +64,8 @@
/* System Controller Registers */
#define SYSCTRL 0x0464
-/* System registers */
#define LPX_PERIOD 3
-/* Lane enable PPI and DSI register bits */
-#define LANEENABLE_CLEN BIT(0)
-#define LANEENABLE_L0EN BIT(1)
-#define LANEENABLE_L1EN BIT(2)
-
struct tc358762 {
struct device *dev;
struct drm_bridge bridge;
@@ -117,7 +116,7 @@ static int tc358762_init(struct tc358762 *ctx)
u32 lcdctrl;
tc358762_write(ctx, DSI_LANEENABLE,
- LANEENABLE_L0EN | LANEENABLE_CLEN);
+ DSI_LANEENABLE_L0EN | DSI_LANEENABLE_CLEN);
tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5);
tc358762_write(ctx, PPI_D1S_CLRSIPOCOUNT, 5);
tc358762_write(ctx, PPI_D0S_ATMR, 0);
@@ -140,8 +139,8 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, SYSCTRL, 0x040f);
msleep(100);
- tc358762_write(ctx, PPI_STARTPPI, PPI_START_FUNCTION);
- tc358762_write(ctx, DSI_STARTDSI, DSI_RX_START);
+ tc358762_write(ctx, PPI_STARTPPI, PPI_STARTPPI_STARTPPI);
+ tc358762_write(ctx, DSI_STARTDSI, DSI_STARTDSI_STARTDSI);
msleep(100);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 02/13] drm/bridge: tc358762: Improve SYSCTRL register defines
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 01/13] drm/bridge: tc358762: Clean up register defines Tomi Valkeinen
@ 2026-09-07 11:27 ` Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 03/13] drm/bridge: tc358762: Improve LCDCTRL defines Tomi Valkeinen
` (11 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:27 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
Define SYSCTRL fields. No functional changes.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index dc20f253c7ad..5630cead7cd8 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -10,6 +10,7 @@
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
@@ -63,6 +64,19 @@
/* System Controller Registers */
#define SYSCTRL 0x0464
+#define SYSCTRL_DPIDATA_IO_MASK GENMASK_U32(1, 0)
+#define SYSCTRL_DPIDATA_IO_1MA 0
+#define SYSCTRL_DPIDATA_IO_2MA 1
+#define SYSCTRL_DPIDATA_IO_3MA 2
+#define SYSCTRL_DPIDATA_IO_4MA 3
+#define SYSCTRL_DPISTB_IO_MASK GENMASK_U32(3, 2)
+#define SYSCTRL_DPISTB_IO_1MA 0
+#define SYSCTRL_DPISTB_IO_2MA 1
+#define SYSCTRL_DPISTB_IO_3MA 2
+#define SYSCTRL_DPISTB_IO_4MA 3
+#define SYSCTRL_PCLKDIV_MASK GENMASK_U32(11, 8)
+#define SYSCTRL_PCLKDIV_DIV_2 2
+#define SYSCTRL_PCLKDIV_DIV_3 4
#define LPX_PERIOD 3
@@ -136,7 +150,11 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, LCDCTRL, lcdctrl);
- tc358762_write(ctx, SYSCTRL, 0x040f);
+ tc358762_write(ctx, SYSCTRL,
+ FIELD_PREP(SYSCTRL_DPIDATA_IO_MASK, SYSCTRL_DPIDATA_IO_4MA) |
+ FIELD_PREP(SYSCTRL_DPISTB_IO_MASK, SYSCTRL_DPISTB_IO_4MA) |
+ FIELD_PREP(SYSCTRL_PCLKDIV_MASK, SYSCTRL_PCLKDIV_DIV_3));
+
msleep(100);
tc358762_write(ctx, PPI_STARTPPI, PPI_STARTPPI_STARTPPI);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 03/13] drm/bridge: tc358762: Improve LCDCTRL defines
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 01/13] drm/bridge: tc358762: Clean up register defines Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 02/13] drm/bridge: tc358762: Improve SYSCTRL " Tomi Valkeinen
@ 2026-09-07 11:27 ` Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 04/13] drm/bridge: tc358762: Configure SYSCTRL first Tomi Valkeinen
` (10 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:27 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
LCDCTRL fields are quite wrong in the driver. Fix the field defines.
A few notes about the wrong fields:
LCDCTRL_VSDELAY(1) actually sets LCDCTRL_DCLK_POL
LCDCTRL_UNK6 | LCDCTRL_VTGEN actually set LCDCTRL_PXLFORM_RGB888
LCDCTRL_RGB888 actually sets LCDCTRL_DPI_EN
The total still resulted in a working display even if the defines were
quite wrong.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 5630cead7cd8..fcd741f5765d 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -46,17 +46,22 @@
#define DSI_LANEENABLE_L0EN BIT(1)
#define DSI_LANEENABLE_L1EN BIT(2)
-/* LCDC/DPI Host Registers, based on guesswork that this matches TC358764 */
+/* LCDC/DPI Registers */
#define LCDCTRL 0x0420 /* Video Path Control */
#define LCDCTRL_MSF BIT(0) /* Magic square in RGB666 */
-#define LCDCTRL_VTGEN BIT(4)/* Use chip clock for timing */
-#define LCDCTRL_UNK6 BIT(6) /* Unknown */
-#define LCDCTRL_EVTMODE BIT(5) /* Event mode */
-#define LCDCTRL_RGB888 BIT(8) /* RGB888 mode */
-#define LCDCTRL_HSPOL BIT(17) /* Polarity of HSYNC signal */
-#define LCDCTRL_DEPOL BIT(18) /* Polarity of DE signal */
-#define LCDCTRL_VSPOL BIT(19) /* Polarity of VSYNC signal */
-#define LCDCTRL_VSDELAY(v) (((v) & 0xfff) << 20) /* VSYNC delay */
+#define LCDCTRL_VTGEN BIT(1) /* Use chip clock for timing */
+#define LCDCTRL_PXLFORM GENMASK_U32(6, 4)
+#define LCDCTRL_PXLFORM_RGB666 0 /* x:R:G:B 6:8:8:8 */
+#define LCDCTRL_PXLFORM_RGB666_24 1 /* x:R:x:G:x:B 2:6:2:6:2:6 */
+#define LCDCTRL_PXLFORM_RGB565 2 /* x:R:G:B 8:5:6:5 */
+#define LCDCTRL_PXLFORM_RGB565_1 3 /* x:R:x:G:x:B 3:5:2:6:3:5 */
+#define LCDCTRL_PXLFORM_RGB565_2 4 /* x:R:x:G:x:B:x 2:5:3:6:2:5:1 */
+#define LCDCTRL_PXLFORM_RGB888 5 /* R:G:B 8:8:8 */
+#define LCDCTRL_DPI_EN BIT(8)
+#define LCDCTRL_HSYNC_POL BIT(17) /* Polarity of HSYNC signal */
+#define LCDCTRL_DE_POL BIT(18) /* Polarity of DE signal */
+#define LCDCTRL_VSYNC_POL BIT(19) /* Polarity of VSYNC signal */
+#define LCDCTRL_DCLK_POL BIT(20) /* Polarity of pixel clock */
/* SPI Master Registers */
#define SPICMR 0x0450
@@ -139,14 +144,16 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, SPICMR, 0x00);
- lcdctrl = LCDCTRL_VSDELAY(1) | LCDCTRL_RGB888 |
- LCDCTRL_UNK6 | LCDCTRL_VTGEN;
+ lcdctrl = FIELD_PREP(LCDCTRL_PXLFORM, LCDCTRL_PXLFORM_RGB888) |
+ LCDCTRL_DPI_EN;
+
+ lcdctrl |= LCDCTRL_DCLK_POL;
if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC)
- lcdctrl |= LCDCTRL_HSPOL;
+ lcdctrl |= LCDCTRL_HSYNC_POL;
if (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC)
- lcdctrl |= LCDCTRL_VSPOL;
+ lcdctrl |= LCDCTRL_VSYNC_POL;
tc358762_write(ctx, LCDCTRL, lcdctrl);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 04/13] drm/bridge: tc358762: Configure SYSCTRL first
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (2 preceding siblings ...)
2026-09-07 11:27 ` [PATCH v4 03/13] drm/bridge: tc358762: Improve LCDCTRL defines Tomi Valkeinen
@ 2026-09-07 11:27 ` Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 05/13] drm/bridge: tc358762: Drop SPICMR write Tomi Valkeinen
` (9 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:27 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
SYSCTRL affects the DPI output and the clock tree, but we configure it
late, when the DPI output is already enabled and clocks are running.
Move the SYSCTRL configuration to the beginning, before anything is
enabled.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index fcd741f5765d..eb6e6ad5b6a1 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -134,6 +134,13 @@ static int tc358762_init(struct tc358762 *ctx)
{
u32 lcdctrl;
+ tc358762_write(ctx, SYSCTRL,
+ FIELD_PREP(SYSCTRL_DPIDATA_IO_MASK, SYSCTRL_DPIDATA_IO_4MA) |
+ FIELD_PREP(SYSCTRL_DPISTB_IO_MASK, SYSCTRL_DPISTB_IO_4MA) |
+ FIELD_PREP(SYSCTRL_PCLKDIV_MASK, SYSCTRL_PCLKDIV_DIV_3));
+
+ msleep(100);
+
tc358762_write(ctx, DSI_LANEENABLE,
DSI_LANEENABLE_L0EN | DSI_LANEENABLE_CLEN);
tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5);
@@ -157,13 +164,6 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, LCDCTRL, lcdctrl);
- tc358762_write(ctx, SYSCTRL,
- FIELD_PREP(SYSCTRL_DPIDATA_IO_MASK, SYSCTRL_DPIDATA_IO_4MA) |
- FIELD_PREP(SYSCTRL_DPISTB_IO_MASK, SYSCTRL_DPISTB_IO_4MA) |
- FIELD_PREP(SYSCTRL_PCLKDIV_MASK, SYSCTRL_PCLKDIV_DIV_3));
-
- msleep(100);
-
tc358762_write(ctx, PPI_STARTPPI, PPI_STARTPPI_STARTPPI);
tc358762_write(ctx, DSI_STARTDSI, DSI_STARTDSI_STARTDSI);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 05/13] drm/bridge: tc358762: Drop SPICMR write
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (3 preceding siblings ...)
2026-09-07 11:27 ` [PATCH v4 04/13] drm/bridge: tc358762: Configure SYSCTRL first Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 06/13] drm/bridge: tc358762: Improve DPI enable handling Tomi Valkeinen
` (8 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen,
Andreas Kemnade
Drop write to SPICMR. It's unclear why the write is there, as SPI is not
supported in the driver, and it's mostly just writing zeroes to already
zero fields (reset defaults). None of the zero bits written disable
anything wrt. SPI.
Reviewed-by: Andreas Kemnade <andreas@kemnade.info>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index eb6e6ad5b6a1..ee72978cd8d8 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -149,8 +149,6 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, PPI_D1S_ATMR, 0);
tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD);
- tc358762_write(ctx, SPICMR, 0x00);
-
lcdctrl = FIELD_PREP(LCDCTRL_PXLFORM, LCDCTRL_PXLFORM_RGB888) |
LCDCTRL_DPI_EN;
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 06/13] drm/bridge: tc358762: Improve DPI enable handling
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (4 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 05/13] drm/bridge: tc358762: Drop SPICMR write Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:36 ` sashiko-bot
2026-09-07 11:28 ` [PATCH v4 07/13] drm/bridge: tc358762: Update comment about the number of lanes Tomi Valkeinen
` (7 subsequent siblings)
13 siblings, 1 reply; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
The HW reset defaults has DPIENABLE bit as set. In the current driver we
configure and enable various things while DPIENABLE is set. This results
in a temporary DPI output with wrong timings, which may cause artifacts
on the panel.
Fix this by clearing DPIEANBLE as the first thing when we start to
enable the display. DPIENABLE is set later with the rest of the LCDCTRL
configuration, and at that time we have done all the other
configurations.
Also, for symmetry and possibly improving the DPI output at disable
time, explicitly disable DPIENABLE when disabling the bridge.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index ee72978cd8d8..7654d4039a9d 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -134,6 +134,12 @@ static int tc358762_init(struct tc358762 *ctx)
{
u32 lcdctrl;
+ /*
+ * DPIENABLE has reset default of 1. Make sure we don't output on
+ * DPI until we have finished the coniguration.
+ */
+ tc358762_write(ctx, LCDCTRL, 0);
+
tc358762_write(ctx, SYSCTRL,
FIELD_PREP(SYSCTRL_DPIDATA_IO_MASK, SYSCTRL_DPIDATA_IO_4MA) |
FIELD_PREP(SYSCTRL_DPISTB_IO_MASK, SYSCTRL_DPISTB_IO_4MA) |
@@ -185,6 +191,9 @@ static void tc358762_post_disable(struct drm_bridge *bridge,
ctx->pre_enabled = false;
+ /* Turn off the DPI output */
+ tc358762_write(ctx, LCDCTRL, 0);
+
if (ctx->reset_gpio)
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 07/13] drm/bridge: tc358762: Update comment about the number of lanes
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (5 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 06/13] drm/bridge: tc358762: Improve DPI enable handling Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 08/13] drm/bridge: tc358762: Support VTG Tomi Valkeinen
` (6 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
Update comment about the number of lanes.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 7654d4039a9d..34f2bfd9977c 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -305,7 +305,14 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
ctx->dev = dev;
ctx->pre_enabled = false;
- /* TODO: Find out how to get dual-lane mode working */
+ /*
+ * When using DSI clk for pixel clock (only mode supported in the driver),
+ * the pclk is derived directly from the DSI byteclk via simple divider,
+ * which is either 2 or 3.
+ * The required divider can be calculated with bitspp / 8 / nlanes. Thus,
+ * for RGB888, only nlanes = 1 works as nlanes = 2 would require divider
+ * of 1.5.
+ */
dsi->lanes = 1;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 08/13] drm/bridge: tc358762: Support VTG
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (6 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 07/13] drm/bridge: tc358762: Update comment about the number of lanes Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 09/13] drm/bridge: tc358762: Fix sync polarities Tomi Valkeinen
` (5 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen,
Andreas Kemnade
TC358762 can generate the DPI output's timings in two ways, either Video
Timings Generator (VTG) on or off:
- VTG off: Duplicate the timings coming from the DSI. This requires DSI
pulse mode.
- VTG on: Sync frame on DSI VSync Start, but the exact output timings
are defined in TC358762 registers. This can be used with DSI
event/burst mode.
We are currently using VTG off in the driver.
I observe that the hsync signal, on my HW setup, is not 100% stable with
VTG off, and it seems to lengthen by a single clock every now and then.
However, it then stabilizes later. To me the DSI input looks solid, but
that is more challenging to measure exactly. So I have not found the
root cause for this.
Turning VTG on removes that instability. As I dont' see any downsides
with enabling VTG (and it would allow extending the driver to use
event/burst mode in the future), let's always enable the VTG.
Reviewed-by: Andreas Kemnade <andreas@kemnade.info>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 34f2bfd9977c..797866265b41 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -18,6 +18,7 @@
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
+#include <video/videomode.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
@@ -63,6 +64,12 @@
#define LCDCTRL_VSYNC_POL BIT(19) /* Polarity of VSYNC signal */
#define LCDCTRL_DCLK_POL BIT(20) /* Polarity of pixel clock */
+#define LCDC_HSR_HBPR 0x0424
+#define LCDC_HDISPR_HFPR 0x0428
+#define LCDC_VSR_VBPR 0x042C
+#define LCDC_VDISPR_VFPR 0x0430
+#define LCDC_VFUEN 0x0434
+
/* SPI Master Registers */
#define SPICMR 0x0450
#define SPITCR 0x0454
@@ -94,6 +101,7 @@ struct tc358762 {
struct drm_display_mode mode;
bool pre_enabled;
int error;
+ bool use_vtg;
};
static int tc358762_clear_error(struct tc358762 *ctx)
@@ -155,9 +163,31 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, PPI_D1S_ATMR, 0);
tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD);
+ if (ctx->use_vtg) {
+ struct videomode vm = { 0 };
+
+ drm_display_mode_to_videomode(&ctx->mode, &vm);
+
+ tc358762_write(ctx, LCDC_HSR_HBPR,
+ vm.hsync_len | (vm.hback_porch << 16));
+ tc358762_write(ctx, LCDC_HDISPR_HFPR,
+ vm.hactive | (vm.hfront_porch << 16));
+
+ tc358762_write(ctx, LCDC_VSR_VBPR,
+ vm.vsync_len | (vm.vback_porch << 16));
+ tc358762_write(ctx, LCDC_VDISPR_VFPR,
+ vm.vactive | (vm.vfront_porch << 16));
+
+ /* Upload VTG timings */
+ tc358762_write(ctx, LCDC_VFUEN, BIT(0));
+ }
+
lcdctrl = FIELD_PREP(LCDCTRL_PXLFORM, LCDCTRL_PXLFORM_RGB888) |
LCDCTRL_DPI_EN;
+ if (ctx->use_vtg)
+ lcdctrl |= LCDCTRL_VTGEN;
+
lcdctrl |= LCDCTRL_DCLK_POL;
if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC)
@@ -305,6 +335,9 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
ctx->dev = dev;
ctx->pre_enabled = false;
+ /* Always use VTG */
+ ctx->use_vtg = true;
+
/*
* When using DSI clk for pixel clock (only mode supported in the driver),
* the pclk is derived directly from the DSI byteclk via simple divider,
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 09/13] drm/bridge: tc358762: Fix sync polarities
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (7 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 08/13] drm/bridge: tc358762: Support VTG Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 10/13] drm/bridge: tc358762: Move tc358762_init() into tc358762_enable() Tomi Valkeinen
` (4 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
Setting LCDCTRL_HSYNC_POL and LCDCTRL_VSYNC_POL will make the respective
sync signal active high. The driver does this in inverse. Fix it.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 797866265b41..3a2e6a97feb8 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -190,10 +190,10 @@ static int tc358762_init(struct tc358762 *ctx)
lcdctrl |= LCDCTRL_DCLK_POL;
- if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC)
+ if (ctx->mode.flags & DRM_MODE_FLAG_PHSYNC)
lcdctrl |= LCDCTRL_HSYNC_POL;
- if (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC)
+ if (ctx->mode.flags & DRM_MODE_FLAG_PVSYNC)
lcdctrl |= LCDCTRL_VSYNC_POL;
tc358762_write(ctx, LCDCTRL, lcdctrl);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 10/13] drm/bridge: tc358762: Move tc358762_init() into tc358762_enable()
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (8 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 09/13] drm/bridge: tc358762: Fix sync polarities Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:38 ` sashiko-bot
2026-09-07 11:28 ` [PATCH v4 11/13] drm/bridge: tc358762: Drop drm_bridge_funcs.mode_set Tomi Valkeinen
` (3 subsequent siblings)
13 siblings, 1 reply; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
The only thing tc358762_enable() does is call tc358762_init(). Inline
the tc358762_init() into tc358762_enable(), for simplicity and to make
it easier to improve the tc358762_enable() in the following commits. No
functional change.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 104 ++++++++++++++++++--------------------
1 file changed, 49 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 3a2e6a97feb8..ff7913441752 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -138,9 +138,56 @@ static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge)
return container_of(bridge, struct tc358762, bridge);
}
-static int tc358762_init(struct tc358762 *ctx)
+static void tc358762_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *state)
+{
+ struct tc358762 *ctx = bridge_to_tc358762(bridge);
+ int ret;
+
+ /*
+ * The post_disable hook might be called multiple times.
+ * We want to avoid regulator imbalance below.
+ */
+ if (!ctx->pre_enabled)
+ return;
+
+ ctx->pre_enabled = false;
+
+ /* Turn off the DPI output */
+ tc358762_write(ctx, LCDCTRL, 0);
+
+ if (ctx->reset_gpio)
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+
+ ret = regulator_disable(ctx->regulator);
+ if (ret < 0)
+ dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
+}
+
+static void tc358762_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *state)
{
+ struct tc358762 *ctx = bridge_to_tc358762(bridge);
+ int ret;
+
+ ret = regulator_enable(ctx->regulator);
+ if (ret < 0)
+ dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);
+
+ if (ctx->reset_gpio) {
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(5000, 10000);
+ }
+
+ ctx->pre_enabled = true;
+}
+
+static void tc358762_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *state)
+{
+ struct tc358762 *ctx = bridge_to_tc358762(bridge);
u32 lcdctrl;
+ int ret;
/*
* DPIENABLE has reset default of 1. Make sure we don't output on
@@ -203,60 +250,7 @@ static int tc358762_init(struct tc358762 *ctx)
msleep(100);
- return tc358762_clear_error(ctx);
-}
-
-static void tc358762_post_disable(struct drm_bridge *bridge,
- struct drm_atomic_commit *state)
-{
- struct tc358762 *ctx = bridge_to_tc358762(bridge);
- int ret;
-
- /*
- * The post_disable hook might be called multiple times.
- * We want to avoid regulator imbalance below.
- */
- if (!ctx->pre_enabled)
- return;
-
- ctx->pre_enabled = false;
-
- /* Turn off the DPI output */
- tc358762_write(ctx, LCDCTRL, 0);
-
- if (ctx->reset_gpio)
- gpiod_set_value_cansleep(ctx->reset_gpio, 0);
-
- ret = regulator_disable(ctx->regulator);
- if (ret < 0)
- dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
-}
-
-static void tc358762_pre_enable(struct drm_bridge *bridge,
- struct drm_atomic_commit *state)
-{
- struct tc358762 *ctx = bridge_to_tc358762(bridge);
- int ret;
-
- ret = regulator_enable(ctx->regulator);
- if (ret < 0)
- dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);
-
- if (ctx->reset_gpio) {
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
- usleep_range(5000, 10000);
- }
-
- ctx->pre_enabled = true;
-}
-
-static void tc358762_enable(struct drm_bridge *bridge,
- struct drm_atomic_commit *state)
-{
- struct tc358762 *ctx = bridge_to_tc358762(bridge);
- int ret;
-
- ret = tc358762_init(ctx);
+ ret = tc358762_clear_error(ctx);
if (ret < 0)
dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 11/13] drm/bridge: tc358762: Drop drm_bridge_funcs.mode_set
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (9 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 10/13] drm/bridge: tc358762: Move tc358762_init() into tc358762_enable() Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 12/13] drm/bridge: tc358762: Set DE_POL and DCLK_POL properly Tomi Valkeinen
` (2 subsequent siblings)
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
drm_bridge_funcs.mode_set is deprecated. Drop it and get the
drm_display_mode from the atomic state.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index ff7913441752..ad3a2620ce47 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -98,7 +98,6 @@ struct tc358762 {
struct regulator *regulator;
struct drm_bridge *panel_bridge;
struct gpio_desc *reset_gpio;
- struct drm_display_mode mode;
bool pre_enabled;
int error;
bool use_vtg;
@@ -186,9 +185,18 @@ static void tc358762_enable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);
+ struct drm_connector_state *conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector *connector;
+ struct drm_display_mode *mode;
u32 lcdctrl;
int ret;
+ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+ mode = &crtc_state->mode;
+
/*
* DPIENABLE has reset default of 1. Make sure we don't output on
* DPI until we have finished the coniguration.
@@ -213,7 +221,7 @@ static void tc358762_enable(struct drm_bridge *bridge,
if (ctx->use_vtg) {
struct videomode vm = { 0 };
- drm_display_mode_to_videomode(&ctx->mode, &vm);
+ drm_display_mode_to_videomode(mode, &vm);
tc358762_write(ctx, LCDC_HSR_HBPR,
vm.hsync_len | (vm.hback_porch << 16));
@@ -237,10 +245,10 @@ static void tc358762_enable(struct drm_bridge *bridge,
lcdctrl |= LCDCTRL_DCLK_POL;
- if (ctx->mode.flags & DRM_MODE_FLAG_PHSYNC)
+ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
lcdctrl |= LCDCTRL_HSYNC_POL;
- if (ctx->mode.flags & DRM_MODE_FLAG_PVSYNC)
+ if (mode->flags & DRM_MODE_FLAG_PVSYNC)
lcdctrl |= LCDCTRL_VSYNC_POL;
tc358762_write(ctx, LCDCTRL, lcdctrl);
@@ -265,15 +273,6 @@ static int tc358762_attach(struct drm_bridge *bridge,
bridge, flags);
}
-static void tc358762_bridge_mode_set(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- const struct drm_display_mode *adj)
-{
- struct tc358762 *ctx = bridge_to_tc358762(bridge);
-
- drm_mode_copy(&ctx->mode, mode);
-}
-
static const struct drm_bridge_funcs tc358762_bridge_funcs = {
.atomic_post_disable = tc358762_post_disable,
.atomic_pre_enable = tc358762_pre_enable,
@@ -282,7 +281,6 @@ static const struct drm_bridge_funcs tc358762_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.attach = tc358762_attach,
- .mode_set = tc358762_bridge_mode_set,
};
static int tc358762_parse_dt(struct tc358762 *ctx)
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 12/13] drm/bridge: tc358762: Set DE_POL and DCLK_POL properly
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (10 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 11/13] drm/bridge: tc358762: Drop drm_bridge_funcs.mode_set Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-07 11:44 ` sashiko-bot
2026-09-07 11:28 ` [PATCH v4 13/13] drm/panel-simple: Fix powertip,ph800480t013-idf02 timings Tomi Valkeinen
2026-09-10 12:20 ` [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Andreas Kemnade
13 siblings, 1 reply; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
The driver hardcodes LCDCTRL_DCLK_POL and ~DE_POL, ignoring what the
panel actuall wants. Fix this by looking at the
bridge_state->output_bus_cfg.flags, and set the polarities correctly.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/bridge/tc358762.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index ad3a2620ce47..25b719cd66fe 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -186,12 +186,15 @@ static void tc358762_enable(struct drm_bridge *bridge,
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);
struct drm_connector_state *conn_state;
+ struct drm_bridge_state *bridge_state;
struct drm_crtc_state *crtc_state;
struct drm_connector *connector;
struct drm_display_mode *mode;
u32 lcdctrl;
int ret;
+ bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
conn_state = drm_atomic_get_new_connector_state(state, connector);
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
@@ -243,7 +246,9 @@ static void tc358762_enable(struct drm_bridge *bridge,
if (ctx->use_vtg)
lcdctrl |= LCDCTRL_VTGEN;
- lcdctrl |= LCDCTRL_DCLK_POL;
+ /* Note: DCLK_POL affects pixdata, de and syncs */
+ if (bridge_state->output_bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
+ lcdctrl |= LCDCTRL_DCLK_POL;
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
lcdctrl |= LCDCTRL_HSYNC_POL;
@@ -251,6 +256,9 @@ static void tc358762_enable(struct drm_bridge *bridge,
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
lcdctrl |= LCDCTRL_VSYNC_POL;
+ if (bridge_state->output_bus_cfg.flags & DRM_BUS_FLAG_DE_LOW)
+ lcdctrl |= LCDCTRL_DE_POL;
+
tc358762_write(ctx, LCDCTRL, lcdctrl);
tc358762_write(ctx, PPI_STARTPPI, PPI_STARTPPI_STARTPPI);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 13/13] drm/panel-simple: Fix powertip,ph800480t013-idf02 timings
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (11 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 12/13] drm/bridge: tc358762: Set DE_POL and DCLK_POL properly Tomi Valkeinen
@ 2026-09-07 11:28 ` Tomi Valkeinen
2026-09-10 12:20 ` [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Andreas Kemnade
13 siblings, 0 replies; 18+ messages in thread
From: Tomi Valkeinen @ 2026-09-07 11:28 UTC (permalink / raw)
To: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: dri-devel, linux-kernel, Dave Stevenson, Tomi Valkeinen
The powertip,ph800480t013-idf02 panel was added to panel-simple, and
with the tc358762 driver, enabled the use of RaspberryPi 7" DSI display.
I have been testing the RaspberryPi 7" DSI display module with TI's
BeagleY-AI, and I can't get a good image with the current panel timings.
It's been quite difficult to figure out exactly what are the issues.
Possibly RPi DSI TX and TI DSI TX have their own quirks which affect
this also. However, now that the tc358762 driver has been fixed wrt. the
signal timings it sends, this patch makes the panel work fine on
BeagleY-AI.
Fix the timings according to the datasheet:
- hsw + hbp must equal to 46. This was correct in the timings, but the
hsw was very tight, and at least Cadence DSI has trouble with such
short hsync. Increase hsw to the middle of the hsw range from the
datasheet, and decrease hbp accordingly.
- vsw + vbp must equal to 23. This was 24, resulting in slight shift in
the image.
- The upstream timings seemed to aim for 50 fps, but this is a normal 60
fps panel, so adjust the timings to get 60 fps. As there's no strict
rule what numbers to pick here, I used the "typical" values from panel
datasheet for pclk, hfp and vfp. However, vfp of 23 instead of the
datasheet's 22 give us a closer match to 60 fps, so I used that.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/panel/panel-simple.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index c09bf3db5e78..02be5e78e253 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -4161,15 +4161,15 @@ static const struct panel_desc powertip_ph128800t006_zhc01 = {
};
static const struct drm_display_mode powertip_ph800480t013_idf02_mode = {
- .clock = 24750,
+ .clock = 33333,
.hdisplay = 800,
- .hsync_start = 800 + 54,
- .hsync_end = 800 + 54 + 2,
- .htotal = 800 + 54 + 2 + 44,
+ .hsync_start = 800 + 210,
+ .hsync_end = 800 + 210 + 20,
+ .htotal = 800 + 210 + 20 + 26,
.vdisplay = 480,
- .vsync_start = 480 + 49,
- .vsync_end = 480 + 49 + 2,
- .vtotal = 480 + 49 + 2 + 22,
+ .vsync_start = 480 + 23,
+ .vsync_end = 480 + 23 + 2,
+ .vtotal = 480 + 23 + 2 + 21,
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
};
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v4 06/13] drm/bridge: tc358762: Improve DPI enable handling
2026-09-07 11:28 ` [PATCH v4 06/13] drm/bridge: tc358762: Improve DPI enable handling Tomi Valkeinen
@ 2026-09-07 11:36 ` sashiko-bot
0 siblings, 0 replies; 18+ messages in thread
From: sashiko-bot @ 2026-09-07 11:36 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unhandled error in tc358762_post_disable() poisons the accumulated error state, silently breaking subsequent bridge initialization.
--
commit 28214859a6b5c3e5c579f3076ec1cf46dc47e5c5
Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
drm/bridge: tc358762: Improve DPI enable handling
This commit clears the DPIENABLE bit early during the display enable
sequence to avoid a temporary DPI output with incorrect timings. It also
disables the DPI output during the bridge disable phase.
> diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
> index ee72978cd8d80..7654d4039a9d7 100644
> --- a/drivers/gpu/drm/bridge/tc358762.c
> +++ b/drivers/gpu/drm/bridge/tc358762.c
> @@ -134,6 +134,12 @@ static int tc358762_init(struct tc358762 *ctx)
> {
> u32 lcdctrl;
>
> + /*
> + * DPIENABLE has reset default of 1. Make sure we don't output on
> + * DPI until we have finished the coniguration.
> + */
> + tc358762_write(ctx, LCDCTRL, 0);
[Severity: High]
If ctx->error is already set from a previous failure, will this write and all
subsequent configuration writes in tc358762_init() be silently skipped?
[ ... ]
> @@ -185,6 +191,9 @@ static void tc358762_post_disable(struct drm_bridge *bridge,
>
> ctx->pre_enabled = false;
>
> + /* Turn off the DPI output */
> + tc358762_write(ctx, LCDCTRL, 0);
[Severity: High]
Does this write need a corresponding tc358762_clear_error() call to clean up
the accumulated error state?
If this DSI write fails during tc358762_post_disable() (e.g., during a DPMS
off cycle or modeset), ctx->error is set. Since it is not cleared in the
teardown path, the error state persists into the next DPMS on cycle.
When the display is later enabled via tc358762_init() or tc358762_enable(),
the lingering ctx->error would cause every tc358762_write() to return
immediately without touching the hardware.
Could this transient failure prevent the hardware from being correctly
configured during the next DPMS on cycle?
> +
> if (ctx->reset_gpio)
> gpiod_set_value_cansleep(ctx->reset_gpio, 0);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260907-tc358762-fixes-v4-0-e3fc3ab5cd83@ideasonboard.com?part=6
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 10/13] drm/bridge: tc358762: Move tc358762_init() into tc358762_enable()
2026-09-07 11:28 ` [PATCH v4 10/13] drm/bridge: tc358762: Move tc358762_init() into tc358762_enable() Tomi Valkeinen
@ 2026-09-07 11:38 ` sashiko-bot
0 siblings, 0 replies; 18+ messages in thread
From: sashiko-bot @ 2026-09-07 11:38 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Sticky error state from post_disable infects subsequent enable sequence.
--
commit f76c8643501a53ed324e8fe4854b3ed95f3e36b5
Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
drm/bridge: tc358762: Move tc358762_init() into tc358762_enable()
The only thing tc358762_enable() does is call tc358762_init(). Inline
the tc358762_init() into tc358762_enable(), for simplicity and to make
it easier to improve the tc358762_enable() in the following commits. No
functional change.
> diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
> index 3a2e6a97feb87..ff79134417522 100644
> --- a/drivers/gpu/drm/bridge/tc358762.c
> +++ b/drivers/gpu/drm/bridge/tc358762.c
> @@ -138,9 +138,56 @@ static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge)
[ ... ]
> +static void tc358762_post_disable(struct drm_bridge *bridge,
> + struct drm_atomic_commit *state)
> +{
[ ... ]
> + ctx->pre_enabled = false;
> +
> + /* Turn off the DPI output */
> + tc358762_write(ctx, LCDCTRL, 0);
[Severity: High]
This isn't a bug introduced by this patch, but if this write fails, it sets
ctx->error which does not appear to be cleared at the end of
tc358762_post_disable(). Could this leak the error state?
> +
> + if (ctx->reset_gpio)
> + gpiod_set_value_cansleep(ctx->reset_gpio, 0);
[ ... ]
> +static void tc358762_enable(struct drm_bridge *bridge,
> + struct drm_atomic_commit *state)
> +{
> + struct tc358762 *ctx = bridge_to_tc358762(bridge);
> u32 lcdctrl;
> + int ret;
>
> /*
> * DPIENABLE has reset default of 1. Make sure we don't output on
[Severity: High]
This is a pre-existing issue, but does a leftover ctx->error from a prior
tc358762_post_disable() cause all subsequent initialization writes in
tc358762_enable() to be silently skipped?
If so, would this cause the display to permanently fail on subsequent enables,
such as after suspend and resume?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260907-tc358762-fixes-v4-0-e3fc3ab5cd83@ideasonboard.com?part=10
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 12/13] drm/bridge: tc358762: Set DE_POL and DCLK_POL properly
2026-09-07 11:28 ` [PATCH v4 12/13] drm/bridge: tc358762: Set DE_POL and DCLK_POL properly Tomi Valkeinen
@ 2026-09-07 11:44 ` sashiko-bot
0 siblings, 0 replies; 18+ messages in thread
From: sashiko-bot @ 2026-09-07 11:44 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Sleeping function msleep() is called in an atomic context path (bridge enable callback).
--
commit 12b0c322f22c1997a91fce2069aabdcb2f3f31cf
Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
drm/bridge: tc358762: Set DE_POL and DCLK_POL properly
This commit updates the tc358762 bridge driver to dynamically set the
LCDCTRL_DCLK_POL and LCDCTRL_DE_POL polarities. Instead of hardcoding these
values, it now reads them from the output bus configuration flags to match
the panel's requirements.
> diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
> index ad3a2620ce476..25b719cd66fec 100644
> --- a/drivers/gpu/drm/bridge/tc358762.c
> +++ b/drivers/gpu/drm/bridge/tc358762.c
> @@ -186,12 +186,15 @@ static void tc358762_enable(struct drm_bridge *bridge,
> {
> struct tc358762 *ctx = bridge_to_tc358762(bridge);
> struct drm_connector_state *conn_state;
> + struct drm_bridge_state *bridge_state;
[Severity: High]
This isn't a bug introduced by this patch, but does this function sleep in
atomic context?
Looking at tc358762_enable() in drivers/gpu/drm/bridge/tc358762.c, there are
two instances where msleep() is called:
drivers/gpu/drm/bridge/tc358762.c:tc358762_enable() {
...
tc358762_write(ctx, SYSCTRL,
FIELD_PREP(SYSCTRL_DPIDATA_IO_MASK, SYSCTRL_DPIDATA_IO_4MA) |
FIELD_PREP(SYSCTRL_DPISTB_IO_MASK, SYSCTRL_DPISTB_IO_4MA) |
FIELD_PREP(SYSCTRL_PCLKDIV_MASK, SYSCTRL_PCLKDIV_DIV_3));
msleep(100);
...
tc358762_write(ctx, PPI_STARTPPI, PPI_STARTPPI_STARTPPI);
tc358762_write(ctx, DSI_STARTDSI, DSI_STARTDSI_STARTDSI);
msleep(100);
...
}
This function is registered as the bridge's atomic enable callback. According
to DRM subsystem guidelines, encoder and bridge atomic enable callbacks run in
atomic context during non-blocking commits where sleeping is forbidden.
Can calling msleep() from this atomic context cause kernel warnings, system
instability, or potential deadlocks when the display pipeline is enabled?
> struct drm_crtc_state *crtc_state;
> struct drm_connector *connector;
> struct drm_display_mode *mode;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260907-tc358762-fixes-v4-0-e3fc3ab5cd83@ideasonboard.com?part=12
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
` (12 preceding siblings ...)
2026-09-07 11:28 ` [PATCH v4 13/13] drm/panel-simple: Fix powertip,ph800480t013-idf02 timings Tomi Valkeinen
@ 2026-09-10 12:20 ` Andreas Kemnade
13 siblings, 0 replies; 18+ messages in thread
From: Andreas Kemnade @ 2026-09-10 12:20 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Marek Vasut, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, dri-devel, linux-kernel, Dave Stevenson
On Mon, 07 Sep 2026 14:27:55 +0300
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> wrote:
> While trying to get Raspberry Pi display v1.1 working on Beagleboard
> platforms, I noticed various small issues with the tc358762 driver.
>
> The series also contains a patch to fix the timings in the
> powertip,ph800480t013-idf02 panel. The combination of tc358762 +
> ph800480t013 is used in the Raspberry Pi display module, so it makes
> sense to fix them together.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
> Changes in v4:
> - Rebased on latest upstream, fixing the minor compilation issues that it
> brought
this sits on v7.2, not v7.3-rc
It does not apply to v7.3-rcX and newer.
Just tried to rebase my stuff for the Epson Moverio BT200 onto this
and found that this does not apply.
Regards,
Andreas
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-09-10 12:21 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-07 11:27 [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 01/13] drm/bridge: tc358762: Clean up register defines Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 02/13] drm/bridge: tc358762: Improve SYSCTRL " Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 03/13] drm/bridge: tc358762: Improve LCDCTRL defines Tomi Valkeinen
2026-09-07 11:27 ` [PATCH v4 04/13] drm/bridge: tc358762: Configure SYSCTRL first Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 05/13] drm/bridge: tc358762: Drop SPICMR write Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 06/13] drm/bridge: tc358762: Improve DPI enable handling Tomi Valkeinen
2026-09-07 11:36 ` sashiko-bot
2026-09-07 11:28 ` [PATCH v4 07/13] drm/bridge: tc358762: Update comment about the number of lanes Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 08/13] drm/bridge: tc358762: Support VTG Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 09/13] drm/bridge: tc358762: Fix sync polarities Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 10/13] drm/bridge: tc358762: Move tc358762_init() into tc358762_enable() Tomi Valkeinen
2026-09-07 11:38 ` sashiko-bot
2026-09-07 11:28 ` [PATCH v4 11/13] drm/bridge: tc358762: Drop drm_bridge_funcs.mode_set Tomi Valkeinen
2026-09-07 11:28 ` [PATCH v4 12/13] drm/bridge: tc358762: Set DE_POL and DCLK_POL properly Tomi Valkeinen
2026-09-07 11:44 ` sashiko-bot
2026-09-07 11:28 ` [PATCH v4 13/13] drm/panel-simple: Fix powertip,ph800480t013-idf02 timings Tomi Valkeinen
2026-09-10 12:20 ` [PATCH v4 00/13] drm/bridge: tc358762: Various small fixes Andreas Kemnade
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox