[PATCH] drm: rcar-du: Don't create encoder for unconnected LVDS outputs
Kieran Bingham
kieran.bingham at ideasonboard.com
Tue Sep 28 11:57:09 UTC 2021
On 22/08/2021 01:36, Laurent Pinchart wrote:
> On R-Car D3 and E3, the LVDS encoders provide the pixel clock to the DU,
> even when LVDS outputs are not used. For this reason, the rcar-lvds
> driver probes successfully on those platforms even if no further bridge
> or panel is connected to the LVDS output, in order to provide the
> rcar_lvds_clk_enable() and rcar_lvds_clk_disable() functions to the DU
> driver.
>
> If an LVDS output isn't connected, trying to create a DRM connector for
> the output will fail. Fix this by skipping connector creation in that
> case, and also skip creation of the DRM encoder as there's no point in
> an encoder without a connector.
>
> Fixes: e9e056949c92 ("drm: rcar-du: lvds: Convert to DRM panel bridge helper")
> Reported-by: Geert Uytterhoeven <geert at linux-m68k.org>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
Perhaps this helps it get upstream...
Reviewed-by: Kieran Bingham <kieran.bingham+renesas at ideasonboard.com>
> ---
> drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 16 ++++++++++++----
> drivers/gpu/drm/rcar-du/rcar_lvds.c | 11 +++++++++++
> drivers/gpu/drm/rcar-du/rcar_lvds.h | 5 +++++
> 3 files changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> index 0daa8bba50f5..4bf4e25d7f01 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> @@ -86,12 +86,20 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
> }
>
> /*
> - * Create and initialize the encoder. On Gen3 skip the LVDS1 output if
> + * Create and initialize the encoder. On Gen3, skip the LVDS1 output if
> * the LVDS1 encoder is used as a companion for LVDS0 in dual-link
> - * mode.
> + * mode, or any LVDS output if it isn't connected. The latter may happen
> + * on D3 or E3 as the LVDS encoders are needed to provide the pixel
> + * clock to the DU, even when the LVDS outputs are not used.
> */
> - if (rcdu->info->gen >= 3 && output == RCAR_DU_OUTPUT_LVDS1) {
> - if (rcar_lvds_dual_link(bridge))
> + if (rcdu->info->gen >= 3) {
> + if (output == RCAR_DU_OUTPUT_LVDS1 &&
> + rcar_lvds_dual_link(bridge))
> + return -ENOLINK;
> +
> + if ((output == RCAR_DU_OUTPUT_LVDS0 ||
> + output == RCAR_DU_OUTPUT_LVDS1) &&
> + !rcar_lvds_is_connected(bridge))
> return -ENOLINK;
> }
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index d061b8de748f..b672c5bd72ee 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -576,6 +576,9 @@ static int rcar_lvds_attach(struct drm_bridge *bridge,
> {
> struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
>
> + if (!lvds->next_bridge)
> + return 0;
> +
> return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge,
> flags);
> }
> @@ -598,6 +601,14 @@ bool rcar_lvds_dual_link(struct drm_bridge *bridge)
> }
> EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
>
> +bool rcar_lvds_is_connected(struct drm_bridge *bridge)
> +{
> + struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
> +
> + return lvds->next_bridge != NULL;
> +}
> +EXPORT_SYMBOL_GPL(rcar_lvds_is_connected);
> +
> /* -----------------------------------------------------------------------------
> * Probe & Remove
> */
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h
> index 222ec0e60785..eb7c6ef03b00 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h
> @@ -16,6 +16,7 @@ struct drm_bridge;
> int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq);
> void rcar_lvds_clk_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)
> @@ -27,6 +28,10 @@ static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge)
> {
> return false;
> }
> +static inline bool rcar_lvds_is_connected(struct drm_bridge *bridge)
> +{
> + return false;
> +}
> #endif /* CONFIG_DRM_RCAR_LVDS */
>
> #endif /* __RCAR_LVDS_H__ */
>
More information about the dri-devel
mailing list