Message ID | 20201216005021.19518-2-laurent.pinchart+renesas@ideasonboard.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Kieran Bingham |
Headers | show |
Series | Converter R-Car DU to the DRM bridge connector helper | expand |
Hi Laurent, On Wed, Dec 16, 2020 at 02:50:18AM +0200, Laurent Pinchart wrote: > Replace the manual panel handling with usage of the DRM panel bridge > helper. This simplifies the driver, and brings support for > DRM_BRIDGE_ATTACH_NO_CONNECTOR as an added bonus. > > Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> > --- > drivers/gpu/drm/rcar-du/rcar_lvds.c | 120 +++------------------------- > 1 file changed, 12 insertions(+), 108 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c > index 70dbbe44bb23..1b360e06658c 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > @@ -63,7 +63,6 @@ struct rcar_lvds { > struct drm_bridge bridge; > > struct drm_bridge *next_bridge; > - struct drm_connector connector; > struct drm_panel *panel; > > void __iomem *mmio; > @@ -80,73 +79,11 @@ struct rcar_lvds { > #define bridge_to_rcar_lvds(b) \ > container_of(b, struct rcar_lvds, bridge) > > -#define connector_to_rcar_lvds(c) \ > - container_of(c, struct rcar_lvds, connector) > - > static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data) > { > iowrite32(data, lvds->mmio + reg); > } > > -/* ----------------------------------------------------------------------------- > - * Connector & Panel > - */ > - > -static int rcar_lvds_connector_get_modes(struct drm_connector *connector) > -{ > - struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); > - > - return drm_panel_get_modes(lvds->panel, connector); > -} > - > -static int rcar_lvds_connector_atomic_check(struct drm_connector *connector, > - struct drm_atomic_state *state) > -{ > - struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); > - const struct drm_display_mode *panel_mode; > - struct drm_connector_state *conn_state; > - struct drm_crtc_state *crtc_state; > - > - conn_state = drm_atomic_get_new_connector_state(state, connector); > - if (!conn_state->crtc) > - return 0; > - > - if (list_empty(&connector->modes)) { > - dev_dbg(lvds->dev, "connector: empty modes list\n"); > - return -EINVAL; > - } > - > - panel_mode = list_first_entry(&connector->modes, > - struct drm_display_mode, head); > - > - /* We're not allowed to modify the resolution. */ > - crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc); > - if (IS_ERR(crtc_state)) > - return PTR_ERR(crtc_state); > - > - if (crtc_state->mode.hdisplay != panel_mode->hdisplay || > - crtc_state->mode.vdisplay != panel_mode->vdisplay) > - return -EINVAL; > - > - /* The flat panel mode is fixed, just copy it to the adjusted mode. */ > - drm_mode_copy(&crtc_state->adjusted_mode, panel_mode); > - > - return 0; > -} > - > -static const struct drm_connector_helper_funcs rcar_lvds_conn_helper_funcs = { > - .get_modes = rcar_lvds_connector_get_modes, > - .atomic_check = rcar_lvds_connector_atomic_check, > -}; > - > -static const struct drm_connector_funcs rcar_lvds_conn_funcs = { > - .reset = drm_atomic_helper_connector_reset, > - .fill_modes = drm_helper_probe_single_connector_modes, > - .destroy = drm_connector_cleanup, > - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > -}; > - > /* ----------------------------------------------------------------------------- > * PLL Setup > */ > @@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, > /* Turn the output on. */ > lvdcr0 |= LVDCR0_LVRES; > rcar_lvds_write(lvds, LVDCR0, lvdcr0); > - > - if (lvds->panel) { > - drm_panel_prepare(lvds->panel); > - drm_panel_enable(lvds->panel); > - } > } > > static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, > @@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, > { > struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); > > - if (lvds->panel) { > - drm_panel_disable(lvds->panel); > - drm_panel_unprepare(lvds->panel); > - } > - > rcar_lvds_write(lvds, LVDCR0, 0); > rcar_lvds_write(lvds, LVDCR1, 0); > rcar_lvds_write(lvds, LVDPLLCR, 0); > @@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge, > enum drm_bridge_attach_flags flags) > { > struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); > - struct drm_connector *connector = &lvds->connector; > - struct drm_encoder *encoder = bridge->encoder; > - int ret; > > - /* If we have a next bridge just attach it. */ > - if (lvds->next_bridge) > - return drm_bridge_attach(bridge->encoder, lvds->next_bridge, > - bridge, flags); > - > - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { > - DRM_ERROR("Fix bridge driver to make connector optional!"); > - return -EINVAL; > - } > - > - /* Otherwise if we have a panel, create a connector. */ > - if (!lvds->panel) > - return 0; > - > - ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs, > - DRM_MODE_CONNECTOR_LVDS); > - if (ret < 0) > - return ret; > - > - drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs); > - > - ret = drm_connector_attach_encoder(connector, encoder); > - if (ret < 0) > - return ret; > - > - return 0; > -} > - > -static void rcar_lvds_detach(struct drm_bridge *bridge) > -{ > + return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge, > + flags); > } > > static const struct drm_bridge_funcs rcar_lvds_bridge_ops = { > .attach = rcar_lvds_attach, > - .detach = rcar_lvds_detach, > .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, > .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, > .atomic_reset = drm_atomic_helper_bridge_reset, > @@ -759,7 +654,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds) > * that we are expected to generate even pixels from the primary > * encoder, and odd pixels from the companion encoder. > */ > - if (lvds->next_bridge && lvds->next_bridge->timings && > + if (lvds->next_bridge->timings && > lvds->next_bridge->timings->dual_link) > lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; > else > @@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) > if (ret) > goto done; > > + if (lvds->panel) { > + lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev, > + lvds->panel); Reading the devm_drm_panel_bridge_add() function documentation: * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector Doesn't this conflict with the drm_bridge_connector_init() called by the encoder in [4/4] ? > + if (IS_ERR_OR_NULL(lvds->next_bridge)) { > + ret = -EINVAL; > + goto done; > + } > + } > + > if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) > ret = rcar_lvds_parse_dt_companion(lvds); > > -- > Regards, > > Laurent Pinchart >
Hi Jacopo, On Wed, Dec 16, 2020 at 02:16:56PM +0100, Jacopo Mondi wrote: > On Wed, Dec 16, 2020 at 02:50:18AM +0200, Laurent Pinchart wrote: > > Replace the manual panel handling with usage of the DRM panel bridge > > helper. This simplifies the driver, and brings support for > > DRM_BRIDGE_ATTACH_NO_CONNECTOR as an added bonus. > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> > > --- > > drivers/gpu/drm/rcar-du/rcar_lvds.c | 120 +++------------------------- > > 1 file changed, 12 insertions(+), 108 deletions(-) > > > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c > > index 70dbbe44bb23..1b360e06658c 100644 > > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > > @@ -63,7 +63,6 @@ struct rcar_lvds { > > struct drm_bridge bridge; > > > > struct drm_bridge *next_bridge; > > - struct drm_connector connector; > > struct drm_panel *panel; > > > > void __iomem *mmio; > > @@ -80,73 +79,11 @@ struct rcar_lvds { > > #define bridge_to_rcar_lvds(b) \ > > container_of(b, struct rcar_lvds, bridge) > > > > -#define connector_to_rcar_lvds(c) \ > > - container_of(c, struct rcar_lvds, connector) > > - > > static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data) > > { > > iowrite32(data, lvds->mmio + reg); > > } > > > > -/* ----------------------------------------------------------------------------- > > - * Connector & Panel > > - */ > > - > > -static int rcar_lvds_connector_get_modes(struct drm_connector *connector) > > -{ > > - struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); > > - > > - return drm_panel_get_modes(lvds->panel, connector); > > -} > > - > > -static int rcar_lvds_connector_atomic_check(struct drm_connector *connector, > > - struct drm_atomic_state *state) > > -{ > > - struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); > > - const struct drm_display_mode *panel_mode; > > - struct drm_connector_state *conn_state; > > - struct drm_crtc_state *crtc_state; > > - > > - conn_state = drm_atomic_get_new_connector_state(state, connector); > > - if (!conn_state->crtc) > > - return 0; > > - > > - if (list_empty(&connector->modes)) { > > - dev_dbg(lvds->dev, "connector: empty modes list\n"); > > - return -EINVAL; > > - } > > - > > - panel_mode = list_first_entry(&connector->modes, > > - struct drm_display_mode, head); > > - > > - /* We're not allowed to modify the resolution. */ > > - crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc); > > - if (IS_ERR(crtc_state)) > > - return PTR_ERR(crtc_state); > > - > > - if (crtc_state->mode.hdisplay != panel_mode->hdisplay || > > - crtc_state->mode.vdisplay != panel_mode->vdisplay) > > - return -EINVAL; > > - > > - /* The flat panel mode is fixed, just copy it to the adjusted mode. */ > > - drm_mode_copy(&crtc_state->adjusted_mode, panel_mode); > > - > > - return 0; > > -} > > - > > -static const struct drm_connector_helper_funcs rcar_lvds_conn_helper_funcs = { > > - .get_modes = rcar_lvds_connector_get_modes, > > - .atomic_check = rcar_lvds_connector_atomic_check, > > -}; > > - > > -static const struct drm_connector_funcs rcar_lvds_conn_funcs = { > > - .reset = drm_atomic_helper_connector_reset, > > - .fill_modes = drm_helper_probe_single_connector_modes, > > - .destroy = drm_connector_cleanup, > > - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > > - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > > -}; > > - > > /* ----------------------------------------------------------------------------- > > * PLL Setup > > */ > > @@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, > > /* Turn the output on. */ > > lvdcr0 |= LVDCR0_LVRES; > > rcar_lvds_write(lvds, LVDCR0, lvdcr0); > > - > > - if (lvds->panel) { > > - drm_panel_prepare(lvds->panel); > > - drm_panel_enable(lvds->panel); > > - } > > } > > > > static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, > > @@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, > > { > > struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); > > > > - if (lvds->panel) { > > - drm_panel_disable(lvds->panel); > > - drm_panel_unprepare(lvds->panel); > > - } > > - > > rcar_lvds_write(lvds, LVDCR0, 0); > > rcar_lvds_write(lvds, LVDCR1, 0); > > rcar_lvds_write(lvds, LVDPLLCR, 0); > > @@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge, > > enum drm_bridge_attach_flags flags) > > { > > struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); > > - struct drm_connector *connector = &lvds->connector; > > - struct drm_encoder *encoder = bridge->encoder; > > - int ret; > > > > - /* If we have a next bridge just attach it. */ > > - if (lvds->next_bridge) > > - return drm_bridge_attach(bridge->encoder, lvds->next_bridge, > > - bridge, flags); > > - > > - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { > > - DRM_ERROR("Fix bridge driver to make connector optional!"); > > - return -EINVAL; > > - } > > - > > - /* Otherwise if we have a panel, create a connector. */ > > - if (!lvds->panel) > > - return 0; > > - > > - ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs, > > - DRM_MODE_CONNECTOR_LVDS); > > - if (ret < 0) > > - return ret; > > - > > - drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs); > > - > > - ret = drm_connector_attach_encoder(connector, encoder); > > - if (ret < 0) > > - return ret; > > - > > - return 0; > > -} > > - > > -static void rcar_lvds_detach(struct drm_bridge *bridge) > > -{ > > + return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge, > > + flags); > > } > > > > static const struct drm_bridge_funcs rcar_lvds_bridge_ops = { > > .attach = rcar_lvds_attach, > > - .detach = rcar_lvds_detach, > > .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, > > .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, > > .atomic_reset = drm_atomic_helper_bridge_reset, > > @@ -759,7 +654,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds) > > * that we are expected to generate even pixels from the primary > > * encoder, and odd pixels from the companion encoder. > > */ > > - if (lvds->next_bridge && lvds->next_bridge->timings && > > + if (lvds->next_bridge->timings && > > lvds->next_bridge->timings->dual_link) > > lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; > > else > > @@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) > > if (ret) > > goto done; > > > > + if (lvds->panel) { > > + lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev, > > + lvds->panel); > > Reading the devm_drm_panel_bridge_add() function documentation: > > * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector > > Doesn't this conflict with the drm_bridge_connector_init() called by > the encoder in [4/4] ? It would, if the documentation was right :-) The function only creates a bridge. A connector will only be created when the bridge is attached without DRM_BRIDGE_ATTACH_NO_CONNECTOR. Would you like to send a patch to fix the documentation ? > > + if (IS_ERR_OR_NULL(lvds->next_bridge)) { > > + ret = -EINVAL; > > + goto done; > > + } > > + } > > + > > if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) > > ret = rcar_lvds_parse_dt_companion(lvds); > >
Hi Laurent, On Wed, Dec 16, 2020 at 03:49:24PM +0200, Laurent Pinchart wrote: > Hi Jacopo, > > > > + if (lvds->panel) { > > > + lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev, > > > + lvds->panel); > > > > Reading the devm_drm_panel_bridge_add() function documentation: > > > > * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector > > > > Doesn't this conflict with the drm_bridge_connector_init() called by > > the encoder in [4/4] ? > > It would, if the documentation was right :-) The function only creates a > bridge. A connector will only be created when the bridge is attached > without DRM_BRIDGE_ATTACH_NO_CONNECTOR. Well, reading it again, it is kind of implied that if NO_CONNECTOR is given to the bridge, no connector will be registered at all. > > Would you like to send a patch to fix the documentation ? > > > > + if (IS_ERR_OR_NULL(lvds->next_bridge)) { > > > + ret = -EINVAL; > > > + goto done; > > > + } > > > + } > > > + > > > if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) > > > ret = rcar_lvds_parse_dt_companion(lvds); > > > > > -- > Regards, > > Laurent Pinchart
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index 70dbbe44bb23..1b360e06658c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -63,7 +63,6 @@ struct rcar_lvds { struct drm_bridge bridge; struct drm_bridge *next_bridge; - struct drm_connector connector; struct drm_panel *panel; void __iomem *mmio; @@ -80,73 +79,11 @@ struct rcar_lvds { #define bridge_to_rcar_lvds(b) \ container_of(b, struct rcar_lvds, bridge) -#define connector_to_rcar_lvds(c) \ - container_of(c, struct rcar_lvds, connector) - static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data) { iowrite32(data, lvds->mmio + reg); } -/* ----------------------------------------------------------------------------- - * Connector & Panel - */ - -static int rcar_lvds_connector_get_modes(struct drm_connector *connector) -{ - struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); - - return drm_panel_get_modes(lvds->panel, connector); -} - -static int rcar_lvds_connector_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) -{ - struct rcar_lvds *lvds = connector_to_rcar_lvds(connector); - const struct drm_display_mode *panel_mode; - struct drm_connector_state *conn_state; - struct drm_crtc_state *crtc_state; - - conn_state = drm_atomic_get_new_connector_state(state, connector); - if (!conn_state->crtc) - return 0; - - if (list_empty(&connector->modes)) { - dev_dbg(lvds->dev, "connector: empty modes list\n"); - return -EINVAL; - } - - panel_mode = list_first_entry(&connector->modes, - struct drm_display_mode, head); - - /* We're not allowed to modify the resolution. */ - crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - - if (crtc_state->mode.hdisplay != panel_mode->hdisplay || - crtc_state->mode.vdisplay != panel_mode->vdisplay) - return -EINVAL; - - /* The flat panel mode is fixed, just copy it to the adjusted mode. */ - drm_mode_copy(&crtc_state->adjusted_mode, panel_mode); - - return 0; -} - -static const struct drm_connector_helper_funcs rcar_lvds_conn_helper_funcs = { - .get_modes = rcar_lvds_connector_get_modes, - .atomic_check = rcar_lvds_connector_atomic_check, -}; - -static const struct drm_connector_funcs rcar_lvds_conn_funcs = { - .reset = drm_atomic_helper_connector_reset, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - /* ----------------------------------------------------------------------------- * PLL Setup */ @@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, /* Turn the output on. */ lvdcr0 |= LVDCR0_LVRES; rcar_lvds_write(lvds, LVDCR0, lvdcr0); - - if (lvds->panel) { - drm_panel_prepare(lvds->panel); - drm_panel_enable(lvds->panel); - } } static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, @@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); - if (lvds->panel) { - drm_panel_disable(lvds->panel); - drm_panel_unprepare(lvds->panel); - } - rcar_lvds_write(lvds, LVDCR0, 0); rcar_lvds_write(lvds, LVDCR1, 0); rcar_lvds_write(lvds, LVDPLLCR, 0); @@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); - struct drm_connector *connector = &lvds->connector; - struct drm_encoder *encoder = bridge->encoder; - int ret; - /* If we have a next bridge just attach it. */ - if (lvds->next_bridge) - return drm_bridge_attach(bridge->encoder, lvds->next_bridge, - bridge, flags); - - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - - /* Otherwise if we have a panel, create a connector. */ - if (!lvds->panel) - return 0; - - ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs, - DRM_MODE_CONNECTOR_LVDS); - if (ret < 0) - return ret; - - drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs); - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret < 0) - return ret; - - return 0; -} - -static void rcar_lvds_detach(struct drm_bridge *bridge) -{ + return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge, + flags); } static const struct drm_bridge_funcs rcar_lvds_bridge_ops = { .attach = rcar_lvds_attach, - .detach = rcar_lvds_detach, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_reset = drm_atomic_helper_bridge_reset, @@ -759,7 +654,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds) * that we are expected to generate even pixels from the primary * encoder, and odd pixels from the companion encoder. */ - if (lvds->next_bridge && lvds->next_bridge->timings && + if (lvds->next_bridge->timings && lvds->next_bridge->timings->dual_link) lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; else @@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) if (ret) goto done; + if (lvds->panel) { + lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev, + lvds->panel); + if (IS_ERR_OR_NULL(lvds->next_bridge)) { + ret = -EINVAL; + goto done; + } + } + if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) ret = rcar_lvds_parse_dt_companion(lvds);
Replace the manual panel handling with usage of the DRM panel bridge helper. This simplifies the driver, and brings support for DRM_BRIDGE_ATTACH_NO_CONNECTOR as an added bonus. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_lvds.c | 120 +++------------------------- 1 file changed, 12 insertions(+), 108 deletions(-)