From 0efb6fd36644a4ba743e26ea7ac532a9d539a3ee Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Wed, 10 Aug 2022 17:37:09 +0900 Subject: [PATCH 01/14] media: vsp1: Add premultiplied alpha support To support DRM blend mode in R-Car DU driver, we must be able to pass a plane with the premultiplied alpha. Adding a new property to vsp1_du_atomic_config allows the R-Car DU driver to pass the premultiplied alpha plane. Signed-off-by: Takanari Hayama Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/renesas/vsp1/vsp1_drm.c | 2 ++ include/media/vsp1.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drm.c b/drivers/media/platform/renesas/vsp1/vsp1_drm.c index 0c2507dc03d6..c6f25200982c 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_drm.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_drm.c @@ -856,6 +856,8 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, rpf->mem.addr[1] = cfg->mem[1]; rpf->mem.addr[2] = cfg->mem[2]; + rpf->format.flags = cfg->premult ? V4L2_PIX_FMT_FLAG_PREMUL_ALPHA : 0; + vsp1->drm->inputs[rpf_index].crop = cfg->src; vsp1->drm->inputs[rpf_index].compose = cfg->dst; vsp1->drm->inputs[rpf_index].zpos = cfg->zpos; diff --git a/include/media/vsp1.h b/include/media/vsp1.h index cc1b0d42ce95..48f4a5023d81 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -51,6 +51,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index, * @dst: destination rectangle on the display (integer coordinates) * @alpha: alpha value (0: fully transparent, 255: fully opaque) * @zpos: Z position of the plane (from 0 to number of planes minus 1) + * @premult: true for premultiplied alpha */ struct vsp1_du_atomic_config { u32 pixelformat; @@ -60,6 +61,7 @@ struct vsp1_du_atomic_config { struct v4l2_rect dst; unsigned int alpha; unsigned int zpos; + bool premult; }; /** From b07f5a4d4457a047104315190930a06fc5f26391 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Wed, 10 Aug 2022 17:37:10 +0900 Subject: [PATCH 02/14] drm: rcar-du: Add DRM_MODE_BLEND_PREMULTI support R-Car DU driver implicitly supports DRM_MODE_BLEND_COVERAGE only. This adds a support for DRM_MODE_BLEND_PREMULTI. As a consequence, DRM_MODE_BLEND_PREMULTI becomes the default. If DRM_MODE_BLEND_COVERAGE is desired, it should be set explicitly. This behavior comes from how DRM blend mode is supported. drm_plane_create_blend_mode_property() creates the blend mode property with the default value of DRM_MODE_BLEND_PREMULTI. This default value cannot be modified from the atomic driver. Signed-off-by: Takanari Hayama Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 10b7f1d0877a..3d560969b59c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -171,6 +171,8 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) format = rcar_du_format_info(state->format->fourcc); cfg.pixelformat = format->v4l2; + cfg.premult = state->state.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI; + vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe, plane->index, &cfg); } @@ -436,6 +438,10 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, drm_plane_create_zpos_property(&plane->plane, i, 0, num_planes - 1); + drm_plane_create_blend_mode_property(&plane->plane, + BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE)); + vsp->num_planes++; } From 0a58c9b11b7958a1c9a2d804c5b45f9ab33609e4 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Wed, 10 Aug 2022 17:37:11 +0900 Subject: [PATCH 03/14] drm: rcar-du: Add DRM_MODE_BLEND_PIXEL_NONE support DRM_MODE_BLEND_PIXEL_NONE ignores an alpha channel. Rcar-du driver supports only 3 formats with an alpha channel (DRM_FORMAT_ARGB1555, DRM_FORMAT_ARGB8888 and DRM_FORMAT_ARGB4444). We simply override the format passed to VSP1 for blending with the pixel format without alpha channel. Suggested-by: Laurent Pinchart Signed-off-by: Takanari Hayama Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 3d560969b59c..e465aef41585 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -152,6 +152,7 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) .alpha = state->state.alpha >> 8, .zpos = state->state.zpos, }; + u32 fourcc = state->format->fourcc; unsigned int i; cfg.src.left = state->state.src.x1 >> 16; @@ -168,7 +169,23 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl) + fb->offsets[i]; - format = rcar_du_format_info(state->format->fourcc); + if (state->state.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE) { + switch (fourcc) { + case DRM_FORMAT_ARGB1555: + fourcc = DRM_FORMAT_XRGB1555; + break; + + case DRM_FORMAT_ARGB4444: + fourcc = DRM_FORMAT_XRGB4444; + break; + + case DRM_FORMAT_ARGB8888: + fourcc = DRM_FORMAT_XRGB8888; + break; + } + } + + format = rcar_du_format_info(fourcc); cfg.pixelformat = format->v4l2; cfg.premult = state->state.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI; @@ -439,6 +456,7 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, num_planes - 1); drm_plane_create_blend_mode_property(&plane->plane, + BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) | BIT(DRM_MODE_BLEND_COVERAGE)); From 48d43c4f3f55f4599c294007644184fdce44dafe Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 17 Aug 2022 16:28:01 +0300 Subject: [PATCH 04/14] drm: rcar-du: Remove unnecessary include rcar_du_regs.h is not needed by rcar_du_drv.c so drop the include. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 00ac233a115e..541c202c993a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -27,7 +27,6 @@ #include "rcar_du_drv.h" #include "rcar_du_kms.h" -#include "rcar_du_regs.h" /* ----------------------------------------------------------------------------- * Device Information From 6d8277cfda96c7dd17a43f645858d2d39a7a4a20 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 17 Aug 2022 16:28:02 +0300 Subject: [PATCH 05/14] drm: rcar-du: Fix r8a779a0 color issue The rcar DU driver on r8a779a0 has a bug causing some specific colors getting converted to transparent colors, which then (usually) show as black pixels on the screen. The reason seems to be that the driver sets PnMR_SPIM_ALP bit in PnMR.SPIM field, which is an illegal setting on r8a779a0. The PnMR_SPIM_EOR bit also illegal. Add a new feature flag for this (lack of a) feature and make sure the bits are zero on r8a779a0. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 3 ++- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 12 +++++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 541c202c993a..a2776f1d6f2c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -506,7 +506,8 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { static const struct rcar_du_device_info rcar_du_r8a779a0_info = { .gen = 3, .features = RCAR_DU_FEATURE_CRTC_IRQ - | RCAR_DU_FEATURE_VSP1_SOURCE, + | RCAR_DU_FEATURE_VSP1_SOURCE + | RCAR_DU_FEATURE_NO_BLENDING, .channels_mask = BIT(1) | BIT(0), .routes = { /* R8A779A0 has two MIPI DSI outputs. */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index bfad7775d9a1..712389c7b3d0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -31,6 +31,7 @@ struct rcar_du_device; #define RCAR_DU_FEATURE_VSP1_SOURCE BIT(2) /* Has inputs from VSP1 */ #define RCAR_DU_FEATURE_INTERLACED BIT(3) /* HW supports interlaced */ #define RCAR_DU_FEATURE_TVM_SYNC BIT(4) /* Has TV switch/sync modes */ +#define RCAR_DU_FEATURE_NO_BLENDING BIT(5) /* PnMR.SPIM does not have ALP nor EOR bits */ #define RCAR_DU_QUIRK_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 9e1f0cbbf642..3772dcc19a5a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -506,8 +506,15 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, unsigned int index, const struct rcar_du_plane_state *state) { - rcar_du_plane_write(rgrp, index, PnMR, - PnMR_SPIM_TP_OFF | state->format->pnmr); + struct rcar_du_device *rcdu = rgrp->dev; + u32 pnmr = state->format->pnmr | PnMR_SPIM_TP_OFF; + + if (rcdu->info->features & RCAR_DU_FEATURE_NO_BLENDING) { + /* No blending. ALP and EOR are not supported. */ + pnmr &= ~(PnMR_SPIM_ALP | PnMR_SPIM_EOR); + } + + rcar_du_plane_write(rgrp, index, PnMR, pnmr); rcar_du_plane_write(rgrp, index, PnDDCR4, state->format->edf | PnDDCR4_CODE); @@ -521,7 +528,6 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, * register to 0 to avoid this. */ - /* TODO: Check if alpha-blending should be disabled in PnMR. */ rcar_du_plane_write(rgrp, index, PnALPHAR, 0); } From b3c0b3105d9f5cd0632faac1af4da1201eb15d82 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 27 Aug 2022 03:10:37 +0300 Subject: [PATCH 06/14] drm: rcar-du: Drop leftovers variables from Makefile Commit 841281fe52a7 ("drm: rcar-du: Drop LVDS device tree backward compatibility") has removed device tree overlay sources used for backward compatibility with old bindings, but forgot to remove related variables from the Makefile. Fix it. Fixes: 841281fe52a7 ("drm: rcar-du: Drop LVDS device tree backward compatibility") Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Reviewed-by: Kieran Bingham --- drivers/gpu/drm/rcar-du/Makefile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index e7275b5e7ec8..6f132325c8b7 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile @@ -14,10 +14,3 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o - -# 'remote-endpoint' is fixed up at run-time -DTC_FLAGS_rcar_du_of_lvds_r8a7790 += -Wno-graph_endpoint -DTC_FLAGS_rcar_du_of_lvds_r8a7791 += -Wno-graph_endpoint -DTC_FLAGS_rcar_du_of_lvds_r8a7793 += -Wno-graph_endpoint -DTC_FLAGS_rcar_du_of_lvds_r8a7795 += -Wno-graph_endpoint -DTC_FLAGS_rcar_du_of_lvds_r8a7796 += -Wno-graph_endpoint From c218dd98d754c2d7129e63e0ee9c327ae599d0b3 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 25 Aug 2022 11:39:04 +0100 Subject: [PATCH 07/14] drm: rcar-du: Drop unused encoder header files Drop unused header files from rcar_du_encoder.c Signed-off-by: Biju Das Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 60d6be78323b..bfd5c087eb0a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -9,18 +9,13 @@ #include #include -#include #include #include -#include -#include -#include #include #include "rcar_du_drv.h" #include "rcar_du_encoder.h" -#include "rcar_du_kms.h" #include "rcar_lvds.h" /* ----------------------------------------------------------------------------- From ef5be86cbfd5250c053c649a56e05faa8b08084d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 25 Aug 2022 11:39:05 +0100 Subject: [PATCH 08/14] drm: rcar-du: Use %p4cc to print 4CC format Use the %p4cc format specifier to print 4CCs, which will provide a more readable message than the raw hex value. Reported-by: Geert Uytterhoeven Signed-off-by: Biju Das Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_writeback.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 21881fb5e84a..8c2719efda2a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -405,8 +405,8 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, format = rcar_du_format_info(mode_cmd->pixel_format); if (format == NULL) { - dev_dbg(dev->dev, "unsupported pixel format %08x\n", - mode_cmd->pixel_format); + dev_dbg(dev->dev, "unsupported pixel format %p4cc\n", + &mode_cmd->pixel_format); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 3772dcc19a5a..d759e0192181 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -625,8 +625,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, *format = rcar_du_format_info(state->fb->format->format); if (*format == NULL) { - dev_dbg(dev->dev, "%s: unsupported format %08x\n", __func__, - state->fb->format->format); + dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__, + &state->fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c index 25f50a297c11..8cd37d7b8ae2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c @@ -166,8 +166,8 @@ static int rcar_du_wb_enc_atomic_check(struct drm_encoder *encoder, wb_state->format = rcar_du_format_info(fb->format->format); if (wb_state->format == NULL) { - dev_dbg(dev->dev, "%s: unsupported format %08x\n", __func__, - fb->format->format); + dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__, + &fb->format->format); return -EINVAL; } From cb90d90ca74b5c91d7b624a0805ddb5041bf4dfc Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Aug 2022 15:47:22 +0300 Subject: [PATCH 09/14] drm: rcar-du: lvds: Rename pclk enable/disable functions The DU driver uses the rcar_lvds_clk_enable() and rcar_lvds_clk_disable() functions enable or disable the pixel clock generated by the LVDS encoder, as it requires that clock for proper DU operation. Rename the functions by replacing "clk" with "pclk" to make it clearer that they related to the pixel clock. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_lvds.c | 8 ++++---- drivers/gpu/drm/rcar-du/rcar_lvds.h | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index fd3b94649a01..d38092d85df7 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -744,7 +744,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, const struct drm_display_mode *mode = &crtc->state->adjusted_mode; - rcar_lvds_clk_enable(bridge, mode->clock * 1000); + rcar_lvds_pclk_enable(bridge, mode->clock * 1000); } rcar_du_crtc_start(rcrtc); @@ -777,7 +777,7 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, * Disable the LVDS clock output, see * rcar_du_crtc_atomic_enable(). */ - rcar_lvds_clk_disable(bridge); + rcar_lvds_pclk_disable(bridge); } spin_lock_irq(&crtc->dev->event_lock); diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index d85aa4bc7f84..81a060c2fe3f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -306,7 +306,7 @@ static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq) * Clock - D3/E3 only */ -int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq) +int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); int ret; @@ -324,9 +324,9 @@ int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq) return 0; } -EXPORT_SYMBOL_GPL(rcar_lvds_clk_enable); +EXPORT_SYMBOL_GPL(rcar_lvds_pclk_enable); -void rcar_lvds_clk_disable(struct drm_bridge *bridge) +void rcar_lvds_pclk_disable(struct drm_bridge *bridge) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); @@ -339,7 +339,7 @@ void rcar_lvds_clk_disable(struct drm_bridge *bridge) clk_disable_unprepare(lvds->clocks.mod); } -EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable); +EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable); /* ----------------------------------------------------------------------------- * Bridge diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h index 3097bf749bec..bee7033b60d6 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.h +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h @@ -13,17 +13,17 @@ struct drm_bridge; #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) -int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq); -void rcar_lvds_clk_disable(struct drm_bridge *bridge); +int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq); +void rcar_lvds_pclk_disable(struct drm_bridge *bridge); bool rcar_lvds_dual_link(struct drm_bridge *bridge); bool rcar_lvds_is_connected(struct drm_bridge *bridge); #else -static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge, - unsigned long freq) +static inline int rcar_lvds_pclk_enable(struct drm_bridge *bridge, + unsigned long freq) { return -ENOSYS; } -static inline void rcar_lvds_clk_disable(struct drm_bridge *bridge) { } +static inline void rcar_lvds_pclk_disable(struct drm_bridge *bridge) { } static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge) { return false; From dbf88d033183cb31a901f602c704408a009a40f6 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Aug 2022 15:47:23 +0300 Subject: [PATCH 10/14] drm: rcar-du: dsi: Properly stop video mode TX The driver does not explicitly stop the video mode transmission when disabling the output. While this doesn't seem to be causing any issues, lets follow the steps described in the documentation and add a rcar_mipi_dsi_stop_video() which stop the video mode transmission. This function will also be used in later patches to stop the video transmission even if the DSI IP is not shut down. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index 62f7eb84ab01..7f2be490fcf8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -542,6 +542,34 @@ static int rcar_mipi_dsi_start_video(struct rcar_mipi_dsi *dsi) return 0; } +static void rcar_mipi_dsi_stop_video(struct rcar_mipi_dsi *dsi) +{ + u32 status; + int ret; + + /* Disable transmission in video mode. */ + rcar_mipi_dsi_clr(dsi, TXVMCR, TXVMCR_EN_VIDEO); + + ret = read_poll_timeout(rcar_mipi_dsi_read, status, + !(status & TXVMSR_ACT), + 2000, 100000, false, dsi, TXVMSR); + if (ret < 0) { + dev_err(dsi->dev, "Failed to disable video transmission\n"); + return; + } + + /* Assert video FIFO clear. */ + rcar_mipi_dsi_set(dsi, TXVMCR, TXVMCR_VFCLR); + + ret = read_poll_timeout(rcar_mipi_dsi_read, status, + !(status & TXVMSR_VFRDY), + 2000, 100000, false, dsi, TXVMSR); + if (ret < 0) { + dev_err(dsi->dev, "Failed to assert video FIFO clear\n"); + return; + } +} + /* ----------------------------------------------------------------------------- * Bridge */ @@ -601,6 +629,7 @@ static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge, { struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); + rcar_mipi_dsi_stop_video(dsi); rcar_mipi_dsi_shutdown(dsi); rcar_mipi_dsi_clk_disable(dsi); } From 222abba69c620875c60b20cf77356f260d360ac8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Aug 2022 15:47:24 +0300 Subject: [PATCH 11/14] drm: rcar-du: dsi: Improve DSI shutdown Improve the DSI shutdown procedure by clearing various bits that were set while enabling the DSI output. There has been no clear issues caused by these, but it's safer to ensure that the features are disabled at the start of the next DSI enable. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index 7f2be490fcf8..9c79fe2fc70b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -441,9 +441,21 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, static void rcar_mipi_dsi_shutdown(struct rcar_mipi_dsi *dsi) { + /* Disable VCLKEN */ + rcar_mipi_dsi_write(dsi, VCLKSET, 0); + + /* Disable DOT clock */ + rcar_mipi_dsi_write(dsi, VCLKSET, 0); + rcar_mipi_dsi_clr(dsi, PHYSETUP, PHYSETUP_RSTZ); rcar_mipi_dsi_clr(dsi, PHYSETUP, PHYSETUP_SHUTDOWNZ); + /* CFGCLK disable */ + rcar_mipi_dsi_clr(dsi, CFGCLKSET, CFGCLKSET_CKEN); + + /* LPCLK disable */ + rcar_mipi_dsi_clr(dsi, LPCLKSET, LPCLKSET_CKEN); + dev_dbg(dsi->dev, "DSI device is shutdown\n"); } From 957fe62d7d15f43d49e8cbacafaff8ede7d6cb30 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Aug 2022 15:47:25 +0300 Subject: [PATCH 12/14] drm: rcar-du: Fix DSI enable & disable sequence The rcar crtc depends on the clock provided from the rcar DSI bridge. When the DSI bridge is disabled, the clock is stopped, which causes the crtc disable to timeout. Also, while I have no issue with the enable, the documentation suggests to enable the DSI before the crtc so that the crtc has its clock enabled at enable time. This is also not done by the current driver. To fix this, we need to keep the DSI bridge enabled until the crtc has disabled itself, and enable the DSI bridge before crtc enables itself. Add functions rcar_mipi_dsi_pclk_enable and rcar_mipi_dsi_pclk_disable to the rcar DSI bridge driver which the rcar driver can use to enable/disable the DSI clock when needed. This is similar to what is already done with the rcar LVDS bridge. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 26 +++++++++++++++++++ drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 ++ drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 4 +++ drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 26 ++++++++++++++----- drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h | 31 +++++++++++++++++++++++ 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index d38092d85df7..3619e1ddeb62 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -29,6 +29,7 @@ #include "rcar_du_regs.h" #include "rcar_du_vsp.h" #include "rcar_lvds.h" +#include "rcar_mipi_dsi.h" static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) { @@ -747,6 +748,18 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, rcar_lvds_pclk_enable(bridge, mode->clock * 1000); } + /* + * Similarly to LVDS, on V3U the dot clock is provided by the DSI + * encoder, and we need to enable the DSI clocks before enabling the CRTC. + */ + if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) && + (rstate->outputs & + (BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) { + struct drm_bridge *bridge = rcdu->dsi[rcrtc->index]; + + rcar_mipi_dsi_pclk_enable(bridge, state); + } + rcar_du_crtc_start(rcrtc); /* @@ -780,6 +793,19 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, rcar_lvds_pclk_disable(bridge); } + if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) && + (rstate->outputs & + (BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) { + struct drm_bridge *bridge = rcdu->dsi[rcrtc->index]; + + /* + * Disable the DSI clock output, see + * rcar_du_crtc_atomic_enable(). + */ + + rcar_mipi_dsi_pclk_disable(bridge); + } + spin_lock_irq(&crtc->dev->event_lock); if (crtc->state->event) { drm_crtc_send_vblank_event(crtc, crtc->state->event); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 712389c7b3d0..5cfa2bb7ad93 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -92,6 +92,7 @@ struct rcar_du_device_info { #define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2) #define RCAR_DU_MAX_VSPS 4 #define RCAR_DU_MAX_LVDS 2 +#define RCAR_DU_MAX_DSI 2 struct rcar_du_device { struct device *dev; @@ -108,6 +109,7 @@ struct rcar_du_device { struct platform_device *cmms[RCAR_DU_MAX_CRTCS]; struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; struct drm_bridge *lvds[RCAR_DU_MAX_LVDS]; + struct drm_bridge *dsi[RCAR_DU_MAX_DSI]; struct { struct drm_property *colorkey; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index bfd5c087eb0a..b1787be31e92 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -79,6 +79,10 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, if (output == RCAR_DU_OUTPUT_LVDS0 || output == RCAR_DU_OUTPUT_LVDS1) rcdu->lvds[output - RCAR_DU_OUTPUT_LVDS0] = bridge; + + if (output == RCAR_DU_OUTPUT_DSI0 || + output == RCAR_DU_OUTPUT_DSI1) + rcdu->dsi[output - RCAR_DU_OUTPUT_DSI0] = bridge; } /* diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index 9c79fe2fc70b..0da3caabfe24 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -25,6 +25,7 @@ #include #include +#include "rcar_mipi_dsi.h" #include "rcar_mipi_dsi_regs.h" struct rcar_mipi_dsi { @@ -598,7 +599,22 @@ static int rcar_mipi_dsi_attach(struct drm_bridge *bridge, static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { - struct drm_atomic_state *state = old_bridge_state->base.state; + struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); + + rcar_mipi_dsi_start_video(dsi); +} + +static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); + + rcar_mipi_dsi_stop_video(dsi); +} + +void rcar_mipi_dsi_pclk_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); const struct drm_display_mode *mode; struct drm_connector *connector; @@ -626,8 +642,6 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, if (ret < 0) goto err_dsi_start_hs; - rcar_mipi_dsi_start_video(dsi); - return; err_dsi_start_hs: @@ -635,16 +649,16 @@ err_dsi_start_hs: err_dsi_startup: rcar_mipi_dsi_clk_disable(dsi); } +EXPORT_SYMBOL_GPL(rcar_mipi_dsi_pclk_enable); -static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge) { struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); - rcar_mipi_dsi_stop_video(dsi); rcar_mipi_dsi_shutdown(dsi); rcar_mipi_dsi_clk_disable(dsi); } +EXPORT_SYMBOL_GPL(rcar_mipi_dsi_pclk_disable); static enum drm_mode_status rcar_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h new file mode 100644 index 000000000000..528a196e6edd --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * R-Car DSI Encoder + * + * Copyright (C) 2022 Renesas Electronics Corporation + * + * Contact: Tomi Valkeinen + */ + +#ifndef __RCAR_MIPI_DSI_H__ +#define __RCAR_MIPI_DSI_H__ + +struct drm_atomic_state; +struct drm_bridge; + +#if IS_ENABLED(CONFIG_DRM_RCAR_MIPI_DSI) +void rcar_mipi_dsi_pclk_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state); +void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge); +#else +static inline void rcar_mipi_dsi_pclk_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ +} + +static inline void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge) +{ +} +#endif /* CONFIG_DRM_RCAR_MIPI_DSI */ + +#endif /* __RCAR_MIPI_DSI_H__ */ From 603c8e130d06fc70e84c9704d74c69f098975453 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Aug 2022 15:47:26 +0300 Subject: [PATCH 13/14] drm: rcar-du: dsi: Fix VCLKSET write rcar_mipi_dsi_startup() writes correct values to VCLKSET, but as it uses or-operation to add the new values to the current value in the register, it should first make sure the fields are cleared. Do this by using rcar_mipi_dsi_write() to write the VCLKSET register with a variable that has all the unused bits zeroed. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index 0da3caabfe24..a7f2b7f66a17 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -415,7 +415,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, /* Enable DOT clock */ vclkset = VCLKSET_CKEN; - rcar_mipi_dsi_set(dsi, VCLKSET, vclkset); + rcar_mipi_dsi_write(dsi, VCLKSET, vclkset); if (dsi_format == 24) vclkset |= VCLKSET_BPP_24; @@ -430,7 +430,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, vclkset |= VCLKSET_COLOR_RGB | VCLKSET_DIV(setup_info.div) | VCLKSET_LANE(dsi->lanes - 1); - rcar_mipi_dsi_set(dsi, VCLKSET, vclkset); + rcar_mipi_dsi_write(dsi, VCLKSET, vclkset); /* After setting VCLKSET register, enable VCLKEN */ rcar_mipi_dsi_set(dsi, VCLKEN, VCLKEN_CKEN); From cee3e5839cedcc71be755580dc9c0b87fd129116 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 31 Aug 2022 22:35:36 +0100 Subject: [PATCH 14/14] dt-bindings: display: bridge: renesas,dw-hdmi: Add resets property The DWC HDMI blocks on R-Car and RZ/G2 SoC's use resets, so to complete the bindings include resets property. This also fixes the below warning when running dtbs_check: arch/arm64/boot/dts/renesas/r8a774b1-hihope-rzg2n-rev2-ex-idk-1110wr.dtb: hdmi@fead0000: Unevaluated properties are not allowed ('resets' was unexpected) From schema: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml While at it mark resets property as required as all the DT sources in the kernel specify resets and update the example node. Signed-off-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Acked-by: Krzysztof Kozlowski Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml index 0c9785c8db51..e3ec697f89e7 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml @@ -38,6 +38,9 @@ properties: clock-names: maxItems: 2 + resets: + maxItems: 1 + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -67,6 +70,7 @@ required: - reg - clocks - clock-names + - resets - interrupts - ports @@ -85,6 +89,7 @@ examples: clocks = <&cpg CPG_CORE R8A7795_CLK_S0D4>, <&cpg CPG_MOD 729>; clock-names = "iahb", "isfr"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 729>; ports { #address-cells = <1>;