[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