[PATCH v8 8/9] drm: renesas: rz-du: Add RZ/G3E (R9A09G047) DU support
From: Tommaso Merciai
Date: Fri Aug 28 2026 - 08:27:29 EST
Add Display Unit driver support for the Renesas RZ/G3E SoC (R9A09G047).
Unlike the other SoCs, it has two DU channels: channel 0 drives the
LVDS encoder in single or dual channel mode and the DSI encoder, while
channel 1 drives the LVDS encoder in single channel mode, the DSI
encoder and the parallel interface.
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@xxxxxxxxxxxxxx>
---
v7->v8
- Modelled using ports/port instead of port/ep.
- Rebased on top of RZ/G3L du support [1]
[1] https://lore.kernel.org/all/20260826174854.199139-1-biju.das.jz@xxxxxxxxxxxxxx/
- Added mode_clock_min, mode_clock_max for parallel output.
- Improved commit msg and commit body.
v6->v7:
- Removed feature flag usage, rebased on top of T2H/N2H LCDC series [1]
[1] https://patchwork.global.renesas.com/project/spl2-reviews/list/?series=694&state=%2A&archive=both
- Reworked commit body as now outputs routing is based on endpoint id
instead of port number.
- Fixed rzg2l_du_r9a09g047_info instead of rzg2l_du_r9a09g047_du_info.
- Added bump of RZG2L_DU_MAX_CRTCS and RZG2L_DU_MAX_VSPS to 2.
v5->v6:
- Aligned ports numbering with the bindings changes.
v4->v5:
- Fixed RG2L_DU_FEATURE_SMUX2_DSI_CLK to RZG2L_DU_FEATURE_SMUX2_DSI_CLK,
update commit body accordingly.
- Added features field documentation.
v3->v4:
- No changes.
v2->v3:
- No changes.
v1->v2:
- Instead of using clk-provider API to select the right parent clock,
based on the outputs. Just set the correct duty cycle based on the
output, this reflects at CPG lvl to select the right parent.
- Updated commit message accordingly.
drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c | 29 ++++++++++++++++++-
drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.h | 3 +-
.../gpu/drm/renesas/rz-du/rzg2l_du_encoder.c | 3 +-
3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
index 0c08701b1502..8143929ed401 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
@@ -75,6 +75,31 @@ static const struct rzg2l_du_device_info rzg2l_du_r9a08g046_info = {
.mode_clock_max = 87000,
};
+static const struct rzg2l_du_device_info rzg2l_du_r9a09g047_info = {
+ .features = RZG2L_DU_FEATURE_CHANNEL_RES,
+ .channels_mask = BIT(0) | BIT(1),
+ .routes = {
+ [RZG2L_DU_OUTPUT_DSI0] = {
+ .possible_crtcs = BIT(0) | BIT(1),
+ .port = 0,
+ },
+ [RZG2L_DU_OUTPUT_DPAD0] = {
+ .possible_crtcs = BIT(1),
+ .port = 1,
+ },
+ [RZG2L_DU_OUTPUT_LVDS0] = {
+ .possible_crtcs = BIT(0),
+ .port = 2,
+ },
+ [RZG2L_DU_OUTPUT_LVDS1] = {
+ .possible_crtcs = BIT(0) | BIT(1),
+ .port = 3,
+ },
+ },
+ .mode_clock_min = 5400,
+ .mode_clock_max = 87000,
+};
+
static const struct rzg2l_du_device_info rzg2l_du_r9a09g057_info = {
.channels_mask = BIT(0),
.routes = {
@@ -102,6 +127,7 @@ static const struct of_device_id rzg2l_du_of_table[] = {
{ .compatible = "renesas,r9a07g043u-du", .data = &rzg2l_du_r9a07g043u_info },
{ .compatible = "renesas,r9a07g044-du", .data = &rzg2l_du_r9a07g044_info },
{ .compatible = "renesas,r9a08g046-du", .data = &rzg2l_du_r9a08g046_info },
+ { .compatible = "renesas,r9a09g047-du", .data = &rzg2l_du_r9a09g047_info },
{ .compatible = "renesas,r9a09g057-du", .data = &rzg2l_du_r9a09g057_info },
{ .compatible = "renesas,r9a09g077-du", .data = &rzg2l_du_r9a09g077_info },
{ /* sentinel */ }
@@ -114,7 +140,8 @@ const char *rzg2l_du_output_name(enum rzg2l_du_output output)
static const char * const names[] = {
[RZG2L_DU_OUTPUT_DSI0] = "DSI0",
[RZG2L_DU_OUTPUT_DPAD0] = "DPAD0",
- [RZG2L_DU_OUTPUT_LVDS0] = "LVDS0"
+ [RZG2L_DU_OUTPUT_LVDS0] = "LVDS0",
+ [RZG2L_DU_OUTPUT_LVDS1] = "LVDS1",
};
if (output >= ARRAY_SIZE(names))
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.h b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.h
index 66ebcbaf0687..326293cf9787 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.h
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.h
@@ -27,6 +27,7 @@ enum rzg2l_du_output {
RZG2L_DU_OUTPUT_DSI0,
RZG2L_DU_OUTPUT_DPAD0,
RZG2L_DU_OUTPUT_LVDS0,
+ RZG2L_DU_OUTPUT_LVDS1,
RZG2L_DU_OUTPUT_MAX,
};
@@ -35,7 +36,7 @@ enum rzg2l_du_output {
* @possible_crtcs: bitmask of possible CRTCs for the output
* @port: device tree port number corresponding to this output route
*
- * The DU has 3 possible outputs (DPAD0, DSI0, LVDS0). Output routing data
+ * The DU has 4 possible outputs (DPAD0, DSI0, LVDS0/1). Output routing data
* specify the valid SoC outputs, which CRTC can drive the output, and the type
* of in-SoC encoder for the output.
*/
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c
index a1b48973aa8e..ff3e70227d2a 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c
@@ -81,7 +81,8 @@ static void rzg2l_du_encoder_atomic_mode_set(struct drm_encoder *encoder,
* - LVDS path has DUTY H/L=4/3, 4/7 duty cycle.
* - DSI/RGB path has symmetric 50% duty cycle.
*/
- if (renc->output == RZG2L_DU_OUTPUT_LVDS0)
+ if (renc->output == RZG2L_DU_OUTPUT_LVDS0 ||
+ renc->output == RZG2L_DU_OUTPUT_LVDS1)
clk_set_duty_cycle(clk_parent, 4, 7);
else
clk_set_duty_cycle(clk_parent, 1, 2);
--
2.54.0