[PATCH 1/9] drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Jacopo Mondi
jacopo at jmondi.org
Mon Dec 14 09:43:20 UTC 2020
Hi Laurent,
On Sat, Dec 05, 2020 at 12:01:31AM +0200, Laurent Pinchart wrote:
> On D3 and E3 platforms, the LVDS encoder includes a PLL that can
> generate a clock for the corresponding CRTC, used even when the CRTC
> output to a non-LVDS port. This mechanism is supported by the driver,
> but the implementation is broken in dual-link LVDS mode. In that case,
> the LVDS1 drm_encoder is skipped, which causes a crash when trying to
> access its bridge later on.
Looking at a dts example with both lvds encoders and RGB output
enabled, I might have missed why the LVDS1 encoder is skipped.
>
> Fix this by storing bridge pointers internally instead of retrieving
> them from the encoder.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
The patch itself looks good!
Reviewed-by: Jacopo Mondi <jacopo+renesas at jmondi.org>
Thanks
j
> ---
> drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 ++--------
> drivers/gpu/drm/rcar-du/rcar_du_drv.h | 3 +++
> drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 4 ++++
> 3 files changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index b5fb941e0f53..e23b9c7b4afe 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -730,13 +730,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
> */
> if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
> rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
> - struct rcar_du_encoder *encoder =
> - rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
> + struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
> const struct drm_display_mode *mode =
> &crtc->state->adjusted_mode;
> - struct drm_bridge *bridge;
>
> - bridge = drm_bridge_chain_get_first_bridge(&encoder->base);
> rcar_lvds_clk_enable(bridge, mode->clock * 1000);
> }
>
> @@ -764,15 +761,12 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
>
> if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
> rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
> - struct rcar_du_encoder *encoder =
> - rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
> - struct drm_bridge *bridge;
> + struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
>
> /*
> * Disable the LVDS clock output, see
> * rcar_du_crtc_atomic_enable().
> */
> - bridge = drm_bridge_chain_get_first_bridge(&encoder->base);
> rcar_lvds_clk_disable(bridge);
> }
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> index 61504c54e2ec..71732fc5df8f 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> @@ -20,6 +20,7 @@
>
> struct clk;
> struct device;
> +struct drm_bridge;
> struct drm_device;
> struct drm_property;
> struct rcar_du_device;
> @@ -71,6 +72,7 @@ struct rcar_du_device_info {
> #define RCAR_DU_MAX_CRTCS 4
> #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
>
> struct rcar_du_device {
> struct device *dev;
> @@ -88,6 +90,7 @@ struct rcar_du_device {
> struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
> 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 {
> 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 b0335da0c161..2d40da98144b 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> @@ -91,6 +91,10 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
> ret = -EPROBE_DEFER;
> goto done;
> }
> +
> + if (output == RCAR_DU_OUTPUT_LVDS0 ||
> + output == RCAR_DU_OUTPUT_LVDS1)
> + rcdu->lvds[output - RCAR_DU_OUTPUT_LVDS0] = bridge;
> }
>
> /*
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the dri-devel
mailing list