Skip to content

Commit

Permalink
drm: rcar-du: Don't create encoder for unconnected LVDS outputs
Browse files Browse the repository at this point in the history
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: e9e0569 ("drm: rcar-du: lvds: Convert to DRM panel bridge helper")
Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
  • Loading branch information
Laurent Pinchart committed Oct 7, 2021
1 parent 1e39445 commit 187502a
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
16 changes: 12 additions & 4 deletions drivers/gpu/drm/rcar-du/rcar_du_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_lvds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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
*/
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_lvds.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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__ */

0 comments on commit 187502a

Please sign in to comment.