Message ID | 20170511183128.25085-5-eric@anholt.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, 11 May 2017 11:31:26 -0700 Eric Anholt <eric@anholt.net> wrote: > Another 100 lines of boilerplate gone. Bridges aren't supported yet, > but will be trivial to add later. > > Signed-off-by: Eric Anholt <eric@anholt.net> > --- > [...] > @@ -1082,28 +993,13 @@ int ltdc_load(struct drm_device *ddev) > > DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); > > - if (ldev->panel) { > + if (ldev->bridge) { > encoder = ltdc_rgb_encoder_create(ddev); > if (!encoder) { > DRM_ERROR("Failed to create RGB encoder\n"); > ret = -EINVAL; > goto err; > } You should have a call to drm_bridge_attach() somewhere, otherwise your panel (and its connector) will not be registered. > - > - connector = ltdc_rgb_connector_create(ddev); > - if (!connector) { > - DRM_ERROR("Failed to create RGB connector\n"); > - ret = -EINVAL; > - goto err; > - } > - > - ret = drm_mode_connector_attach_encoder(connector, encoder); > - if (ret) { > - DRM_ERROR("Failed to attach connector to encoder\n"); > - goto err; > - } > - > - drm_panel_attach(ldev->panel, connector); > } >
Hi Eric, I took your patch for the panel-bridge and it works perfectly in both DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi), bravo :-) ~160 lines have been removed from ltdc.c thanks to your panel-bridge code! Many thanks Philippe On 05/11/2017 08:31 PM, Eric Anholt wrote: > Another 100 lines of boilerplate gone. Bridges aren't supported yet, > but will be trivial to add later. > > Signed-off-by: Eric Anholt <eric@anholt.net> > --- > > Also untested. > > drivers/gpu/drm/stm/ltdc.c | 128 +++++---------------------------------------- > drivers/gpu/drm/stm/ltdc.h | 2 +- > 2 files changed, 13 insertions(+), 117 deletions(-) > > diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c > index a40418cda74a..41a1c5d68f5b 100644 > --- a/drivers/gpu/drm/stm/ltdc.c > +++ b/drivers/gpu/drm/stm/ltdc.c > @@ -269,11 +269,6 @@ static inline struct ltdc_device *encoder_to_ltdc(struct drm_encoder *enc) > return (struct ltdc_device *)enc->dev->dev_private; > } > > -static inline struct ltdc_device *connector_to_ltdc(struct drm_connector *con) > -{ > - return (struct ltdc_device *)con->dev->dev_private; > -} > - > static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) > { > enum ltdc_pix_fmt pf; > @@ -815,22 +810,12 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) > > static void ltdc_rgb_encoder_enable(struct drm_encoder *encoder) > { > - struct ltdc_device *ldev = encoder_to_ltdc(encoder); > - > DRM_DEBUG_DRIVER("\n"); > - > - drm_panel_prepare(ldev->panel); > - drm_panel_enable(ldev->panel); > } > > static void ltdc_rgb_encoder_disable(struct drm_encoder *encoder) > { > - struct ltdc_device *ldev = encoder_to_ltdc(encoder); > - > DRM_DEBUG_DRIVER("\n"); > - > - drm_panel_disable(ldev->panel); > - drm_panel_unprepare(ldev->panel); > } > > static const struct drm_encoder_helper_funcs ltdc_rgb_encoder_helper_funcs = { > @@ -863,82 +848,6 @@ static struct drm_encoder *ltdc_rgb_encoder_create(struct drm_device *ddev) > return encoder; > } > > -/* > - * DRM_CONNECTOR > - */ > - > -static int ltdc_rgb_connector_get_modes(struct drm_connector *connector) > -{ > - struct drm_device *ddev = connector->dev; > - struct ltdc_device *ldev = ddev->dev_private; > - int ret = 0; > - > - DRM_DEBUG_DRIVER("\n"); > - > - if (ldev->panel) > - ret = drm_panel_get_modes(ldev->panel); > - > - return ret < 0 ? 0 : ret; > -} > - > -static struct drm_connector_helper_funcs ltdc_rgb_connector_helper_funcs = { > - .get_modes = ltdc_rgb_connector_get_modes, > -}; > - > -static enum drm_connector_status > -ltdc_rgb_connector_detect(struct drm_connector *connector, bool force) > -{ > - struct ltdc_device *ldev = connector_to_ltdc(connector); > - > - return ldev->panel ? connector_status_connected : > - connector_status_disconnected; > -} > - > -static void ltdc_rgb_connector_destroy(struct drm_connector *connector) > -{ > - DRM_DEBUG_DRIVER("\n"); > - > - drm_connector_unregister(connector); > - drm_connector_cleanup(connector); > -} > - > -static const struct drm_connector_funcs ltdc_rgb_connector_funcs = { > - .dpms = drm_atomic_helper_connector_dpms, > - .fill_modes = drm_helper_probe_single_connector_modes, > - .detect = ltdc_rgb_connector_detect, > - .destroy = ltdc_rgb_connector_destroy, > - .reset = drm_atomic_helper_connector_reset, > - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > -}; > - > -struct drm_connector *ltdc_rgb_connector_create(struct drm_device *ddev) > -{ > - struct drm_connector *connector; > - int err; > - > - connector = devm_kzalloc(ddev->dev, sizeof(*connector), GFP_KERNEL); > - if (!connector) { > - DRM_ERROR("Failed to allocate connector\n"); > - return NULL; > - } > - > - connector->polled = DRM_CONNECTOR_POLL_HPD; > - > - err = drm_connector_init(ddev, connector, <dc_rgb_connector_funcs, > - DRM_MODE_CONNECTOR_DPI); > - if (err) { > - DRM_ERROR("Failed to initialize connector\n"); > - return NULL; > - } > - > - drm_connector_helper_add(connector, <dc_rgb_connector_helper_funcs); > - > - DRM_DEBUG_DRIVER("RGB connector:%d created\n", connector->base.id); > - > - return connector; > -} > - > static int ltdc_get_caps(struct drm_device *ddev) > { > struct ltdc_device *ldev = ddev->dev_private; > @@ -972,7 +881,7 @@ static int ltdc_get_caps(struct drm_device *ddev) > return 0; > } > > -static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) > +static struct drm_bridge *ltdc_get_bridge(struct drm_device *ddev) > { > struct device *dev = ddev->dev; > struct device_node *np = dev->of_node; > @@ -1004,7 +913,10 @@ static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) > } > } > > - return panel; > + if (!panel) > + return ERR_PTR(-ENODEV); > + > + return drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); > } > > int ltdc_load(struct drm_device *ddev) > @@ -1014,7 +926,6 @@ int ltdc_load(struct drm_device *ddev) > struct device *dev = ddev->dev; > struct device_node *np = dev->of_node; > struct drm_encoder *encoder; > - struct drm_connector *connector = NULL; > struct drm_crtc *crtc; > struct reset_control *rstc; > struct resource res; > @@ -1022,8 +933,8 @@ int ltdc_load(struct drm_device *ddev) > > DRM_DEBUG_DRIVER("\n"); > > - ldev->panel = ltdc_get_panel(ddev); > - if (!ldev->panel) > + ldev->bridge = ltdc_get_bridge(ddev); > + if (!ldev->bridge) > return -EPROBE_DEFER; > > rstc = of_reset_control_get(np, NULL); > @@ -1082,28 +993,13 @@ int ltdc_load(struct drm_device *ddev) > > DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); > > - if (ldev->panel) { > + if (ldev->bridge) { > encoder = ltdc_rgb_encoder_create(ddev); > if (!encoder) { > DRM_ERROR("Failed to create RGB encoder\n"); > ret = -EINVAL; > goto err; > } > - > - connector = ltdc_rgb_connector_create(ddev); > - if (!connector) { > - DRM_ERROR("Failed to create RGB connector\n"); > - ret = -EINVAL; > - goto err; > - } > - > - ret = drm_mode_connector_attach_encoder(connector, encoder); > - if (ret) { > - DRM_ERROR("Failed to attach connector to encoder\n"); > - goto err; > - } > - > - drm_panel_attach(ldev->panel, connector); > } > > crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); > @@ -1130,8 +1026,8 @@ int ltdc_load(struct drm_device *ddev) > > return 0; > err: > - if (ldev->panel) > - drm_panel_detach(ldev->panel); > + if (ldev->bridge) > + drm_panel_bridge_remove(ldev->bridge); > > clk_disable_unprepare(ldev->pixel_clk); > > @@ -1146,8 +1042,8 @@ void ltdc_unload(struct drm_device *ddev) > > drm_vblank_cleanup(ddev); > > - if (ldev->panel) > - drm_panel_detach(ldev->panel); > + if (ldev->bridge) > + drm_panel_bridge_remove(ldev->bridge); > > clk_disable_unprepare(ldev->pixel_clk); > } > diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h > index d7a9c736ac1e..d78cb0dd3200 100644 > --- a/drivers/gpu/drm/stm/ltdc.h > +++ b/drivers/gpu/drm/stm/ltdc.h > @@ -24,7 +24,7 @@ struct ltdc_device { > struct drm_fbdev_cma *fbdev; > void __iomem *regs; > struct clk *pixel_clk; /* lcd pixel clock */ > - struct drm_panel *panel; > + struct drm_bridge *bridge; > struct mutex err_lock; /* protecting error_status */ > struct ltdc_caps caps; > u32 clut[256]; /* color look up table */ >
Hi Philippe, Le Tue, 30 May 2017 16:55:42 +0000, Philippe CORNU <philippe.cornu@st.com> a écrit : > Hi Eric, > > I took your patch for the panel-bridge and it works perfectly in both > DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi), bravo :-) I still don't understand how it can work without a call to drm_bridge_attach() (which is used to link the RGB encoder to the DPI connector). I'm probably missing something obvious. Maybe someone can point it out :-). Thanks, Boris > > ~160 lines have been removed from ltdc.c thanks to your panel-bridge code! > > Many thanks > Philippe > > On 05/11/2017 08:31 PM, Eric Anholt wrote: > > Another 100 lines of boilerplate gone. Bridges aren't supported yet, > > but will be trivial to add later. > > > > Signed-off-by: Eric Anholt <eric@anholt.net> > > --- > > > > Also untested. > > > > drivers/gpu/drm/stm/ltdc.c | 128 +++++---------------------------------------- > > drivers/gpu/drm/stm/ltdc.h | 2 +- > > 2 files changed, 13 insertions(+), 117 deletions(-) > > > > diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c > > index a40418cda74a..41a1c5d68f5b 100644 > > --- a/drivers/gpu/drm/stm/ltdc.c > > +++ b/drivers/gpu/drm/stm/ltdc.c > > @@ -269,11 +269,6 @@ static inline struct ltdc_device *encoder_to_ltdc(struct drm_encoder *enc) > > return (struct ltdc_device *)enc->dev->dev_private; > > } > > > > -static inline struct ltdc_device *connector_to_ltdc(struct drm_connector *con) > > -{ > > - return (struct ltdc_device *)con->dev->dev_private; > > -} > > - > > static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) > > { > > enum ltdc_pix_fmt pf; > > @@ -815,22 +810,12 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) > > > > static void ltdc_rgb_encoder_enable(struct drm_encoder *encoder) > > { > > - struct ltdc_device *ldev = encoder_to_ltdc(encoder); > > - > > DRM_DEBUG_DRIVER("\n"); > > - > > - drm_panel_prepare(ldev->panel); > > - drm_panel_enable(ldev->panel); > > } > > > > static void ltdc_rgb_encoder_disable(struct drm_encoder *encoder) > > { > > - struct ltdc_device *ldev = encoder_to_ltdc(encoder); > > - > > DRM_DEBUG_DRIVER("\n"); > > - > > - drm_panel_disable(ldev->panel); > > - drm_panel_unprepare(ldev->panel); > > } > > > > static const struct drm_encoder_helper_funcs ltdc_rgb_encoder_helper_funcs = { > > @@ -863,82 +848,6 @@ static struct drm_encoder *ltdc_rgb_encoder_create(struct drm_device *ddev) > > return encoder; > > } > > > > -/* > > - * DRM_CONNECTOR > > - */ > > - > > -static int ltdc_rgb_connector_get_modes(struct drm_connector *connector) > > -{ > > - struct drm_device *ddev = connector->dev; > > - struct ltdc_device *ldev = ddev->dev_private; > > - int ret = 0; > > - > > - DRM_DEBUG_DRIVER("\n"); > > - > > - if (ldev->panel) > > - ret = drm_panel_get_modes(ldev->panel); > > - > > - return ret < 0 ? 0 : ret; > > -} > > - > > -static struct drm_connector_helper_funcs ltdc_rgb_connector_helper_funcs = { > > - .get_modes = ltdc_rgb_connector_get_modes, > > -}; > > - > > -static enum drm_connector_status > > -ltdc_rgb_connector_detect(struct drm_connector *connector, bool force) > > -{ > > - struct ltdc_device *ldev = connector_to_ltdc(connector); > > - > > - return ldev->panel ? connector_status_connected : > > - connector_status_disconnected; > > -} > > - > > -static void ltdc_rgb_connector_destroy(struct drm_connector *connector) > > -{ > > - DRM_DEBUG_DRIVER("\n"); > > - > > - drm_connector_unregister(connector); > > - drm_connector_cleanup(connector); > > -} > > - > > -static const struct drm_connector_funcs ltdc_rgb_connector_funcs = { > > - .dpms = drm_atomic_helper_connector_dpms, > > - .fill_modes = drm_helper_probe_single_connector_modes, > > - .detect = ltdc_rgb_connector_detect, > > - .destroy = ltdc_rgb_connector_destroy, > > - .reset = drm_atomic_helper_connector_reset, > > - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > > - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > > -}; > > - > > -struct drm_connector *ltdc_rgb_connector_create(struct drm_device *ddev) > > -{ > > - struct drm_connector *connector; > > - int err; > > - > > - connector = devm_kzalloc(ddev->dev, sizeof(*connector), GFP_KERNEL); > > - if (!connector) { > > - DRM_ERROR("Failed to allocate connector\n"); > > - return NULL; > > - } > > - > > - connector->polled = DRM_CONNECTOR_POLL_HPD; > > - > > - err = drm_connector_init(ddev, connector, <dc_rgb_connector_funcs, > > - DRM_MODE_CONNECTOR_DPI); > > - if (err) { > > - DRM_ERROR("Failed to initialize connector\n"); > > - return NULL; > > - } > > - > > - drm_connector_helper_add(connector, <dc_rgb_connector_helper_funcs); > > - > > - DRM_DEBUG_DRIVER("RGB connector:%d created\n", connector->base.id); > > - > > - return connector; > > -} > > - > > static int ltdc_get_caps(struct drm_device *ddev) > > { > > struct ltdc_device *ldev = ddev->dev_private; > > @@ -972,7 +881,7 @@ static int ltdc_get_caps(struct drm_device *ddev) > > return 0; > > } > > > > -static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) > > +static struct drm_bridge *ltdc_get_bridge(struct drm_device *ddev) > > { > > struct device *dev = ddev->dev; > > struct device_node *np = dev->of_node; > > @@ -1004,7 +913,10 @@ static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) > > } > > } > > > > - return panel; > > + if (!panel) > > + return ERR_PTR(-ENODEV); > > + > > + return drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); > > } > > > > int ltdc_load(struct drm_device *ddev) > > @@ -1014,7 +926,6 @@ int ltdc_load(struct drm_device *ddev) > > struct device *dev = ddev->dev; > > struct device_node *np = dev->of_node; > > struct drm_encoder *encoder; > > - struct drm_connector *connector = NULL; > > struct drm_crtc *crtc; > > struct reset_control *rstc; > > struct resource res; > > @@ -1022,8 +933,8 @@ int ltdc_load(struct drm_device *ddev) > > > > DRM_DEBUG_DRIVER("\n"); > > > > - ldev->panel = ltdc_get_panel(ddev); > > - if (!ldev->panel) > > + ldev->bridge = ltdc_get_bridge(ddev); > > + if (!ldev->bridge) > > return -EPROBE_DEFER; > > > > rstc = of_reset_control_get(np, NULL); > > @@ -1082,28 +993,13 @@ int ltdc_load(struct drm_device *ddev) > > > > DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); > > > > - if (ldev->panel) { > > + if (ldev->bridge) { > > encoder = ltdc_rgb_encoder_create(ddev); > > if (!encoder) { > > DRM_ERROR("Failed to create RGB encoder\n"); > > ret = -EINVAL; > > goto err; > > } > > - > > - connector = ltdc_rgb_connector_create(ddev); > > - if (!connector) { > > - DRM_ERROR("Failed to create RGB connector\n"); > > - ret = -EINVAL; > > - goto err; > > - } > > - > > - ret = drm_mode_connector_attach_encoder(connector, encoder); > > - if (ret) { > > - DRM_ERROR("Failed to attach connector to encoder\n"); > > - goto err; > > - } > > - > > - drm_panel_attach(ldev->panel, connector); > > } > > > > crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); > > @@ -1130,8 +1026,8 @@ int ltdc_load(struct drm_device *ddev) > > > > return 0; > > err: > > - if (ldev->panel) > > - drm_panel_detach(ldev->panel); > > + if (ldev->bridge) > > + drm_panel_bridge_remove(ldev->bridge); > > > > clk_disable_unprepare(ldev->pixel_clk); > > > > @@ -1146,8 +1042,8 @@ void ltdc_unload(struct drm_device *ddev) > > > > drm_vblank_cleanup(ddev); > > > > - if (ldev->panel) > > - drm_panel_detach(ldev->panel); > > + if (ldev->bridge) > > + drm_panel_bridge_remove(ldev->bridge); > > > > clk_disable_unprepare(ldev->pixel_clk); > > } > > diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h > > index d7a9c736ac1e..d78cb0dd3200 100644 > > --- a/drivers/gpu/drm/stm/ltdc.h > > +++ b/drivers/gpu/drm/stm/ltdc.h > > @@ -24,7 +24,7 @@ struct ltdc_device { > > struct drm_fbdev_cma *fbdev; > > void __iomem *regs; > > struct clk *pixel_clk; /* lcd pixel clock */ > > - struct drm_panel *panel; > > + struct drm_bridge *bridge; > > struct mutex err_lock; /* protecting error_status */ > > struct ltdc_caps caps; > > u32 clut[256]; /* color look up table */ > >
Hi Boris, On 05/31/2017 11:56 AM, Boris Brezillon wrote: > Hi Philippe, > > Le Tue, 30 May 2017 16:55:42 +0000, > Philippe CORNU <philippe.cornu@st.com> a écrit : > >> Hi Eric, >> >> I took your patch for the panel-bridge and it works perfectly in both >> DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi), bravo :-) > > I still don't understand how it can work without a call to > drm_bridge_attach() (which is used to link the RGB encoder to the DPI > connector). I'm probably missing something obvious. Maybe someone can > point it out :-). I think the expectation is that there will be a follow-up patch that would add bridge support. Philippe had posted a patch for adding bridges to ltdc before: https://patchwork.kernel.org/patch/9724835/ He can now redo his patch over Eric's panel-bridge patch-set. Thanks, Archit > > Thanks, > > Boris > >> >> ~160 lines have been removed from ltdc.c thanks to your panel-bridge code! >> >> Many thanks >> Philippe >> >> On 05/11/2017 08:31 PM, Eric Anholt wrote: >>> Another 100 lines of boilerplate gone. Bridges aren't supported yet, >>> but will be trivial to add later. >>> >>> Signed-off-by: Eric Anholt <eric@anholt.net> >>> --- >>> >>> Also untested. >>> >>> drivers/gpu/drm/stm/ltdc.c | 128 +++++---------------------------------------- >>> drivers/gpu/drm/stm/ltdc.h | 2 +- >>> 2 files changed, 13 insertions(+), 117 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c >>> index a40418cda74a..41a1c5d68f5b 100644 >>> --- a/drivers/gpu/drm/stm/ltdc.c >>> +++ b/drivers/gpu/drm/stm/ltdc.c >>> @@ -269,11 +269,6 @@ static inline struct ltdc_device *encoder_to_ltdc(struct drm_encoder *enc) >>> return (struct ltdc_device *)enc->dev->dev_private; >>> } >>> >>> -static inline struct ltdc_device *connector_to_ltdc(struct drm_connector *con) >>> -{ >>> - return (struct ltdc_device *)con->dev->dev_private; >>> -} >>> - >>> static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) >>> { >>> enum ltdc_pix_fmt pf; >>> @@ -815,22 +810,12 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) >>> >>> static void ltdc_rgb_encoder_enable(struct drm_encoder *encoder) >>> { >>> - struct ltdc_device *ldev = encoder_to_ltdc(encoder); >>> - >>> DRM_DEBUG_DRIVER("\n"); >>> - >>> - drm_panel_prepare(ldev->panel); >>> - drm_panel_enable(ldev->panel); >>> } >>> >>> static void ltdc_rgb_encoder_disable(struct drm_encoder *encoder) >>> { >>> - struct ltdc_device *ldev = encoder_to_ltdc(encoder); >>> - >>> DRM_DEBUG_DRIVER("\n"); >>> - >>> - drm_panel_disable(ldev->panel); >>> - drm_panel_unprepare(ldev->panel); >>> } >>> >>> static const struct drm_encoder_helper_funcs ltdc_rgb_encoder_helper_funcs = { >>> @@ -863,82 +848,6 @@ static struct drm_encoder *ltdc_rgb_encoder_create(struct drm_device *ddev) >>> return encoder; >>> } >>> >>> -/* >>> - * DRM_CONNECTOR >>> - */ >>> - >>> -static int ltdc_rgb_connector_get_modes(struct drm_connector *connector) >>> -{ >>> - struct drm_device *ddev = connector->dev; >>> - struct ltdc_device *ldev = ddev->dev_private; >>> - int ret = 0; >>> - >>> - DRM_DEBUG_DRIVER("\n"); >>> - >>> - if (ldev->panel) >>> - ret = drm_panel_get_modes(ldev->panel); >>> - >>> - return ret < 0 ? 0 : ret; >>> -} >>> - >>> -static struct drm_connector_helper_funcs ltdc_rgb_connector_helper_funcs = { >>> - .get_modes = ltdc_rgb_connector_get_modes, >>> -}; >>> - >>> -static enum drm_connector_status >>> -ltdc_rgb_connector_detect(struct drm_connector *connector, bool force) >>> -{ >>> - struct ltdc_device *ldev = connector_to_ltdc(connector); >>> - >>> - return ldev->panel ? connector_status_connected : >>> - connector_status_disconnected; >>> -} >>> - >>> -static void ltdc_rgb_connector_destroy(struct drm_connector *connector) >>> -{ >>> - DRM_DEBUG_DRIVER("\n"); >>> - >>> - drm_connector_unregister(connector); >>> - drm_connector_cleanup(connector); >>> -} >>> - >>> -static const struct drm_connector_funcs ltdc_rgb_connector_funcs = { >>> - .dpms = drm_atomic_helper_connector_dpms, >>> - .fill_modes = drm_helper_probe_single_connector_modes, >>> - .detect = ltdc_rgb_connector_detect, >>> - .destroy = ltdc_rgb_connector_destroy, >>> - .reset = drm_atomic_helper_connector_reset, >>> - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, >>> - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, >>> -}; >>> - >>> -struct drm_connector *ltdc_rgb_connector_create(struct drm_device *ddev) >>> -{ >>> - struct drm_connector *connector; >>> - int err; >>> - >>> - connector = devm_kzalloc(ddev->dev, sizeof(*connector), GFP_KERNEL); >>> - if (!connector) { >>> - DRM_ERROR("Failed to allocate connector\n"); >>> - return NULL; >>> - } >>> - >>> - connector->polled = DRM_CONNECTOR_POLL_HPD; >>> - >>> - err = drm_connector_init(ddev, connector, <dc_rgb_connector_funcs, >>> - DRM_MODE_CONNECTOR_DPI); >>> - if (err) { >>> - DRM_ERROR("Failed to initialize connector\n"); >>> - return NULL; >>> - } >>> - >>> - drm_connector_helper_add(connector, <dc_rgb_connector_helper_funcs); >>> - >>> - DRM_DEBUG_DRIVER("RGB connector:%d created\n", connector->base.id); >>> - >>> - return connector; >>> -} >>> - >>> static int ltdc_get_caps(struct drm_device *ddev) >>> { >>> struct ltdc_device *ldev = ddev->dev_private; >>> @@ -972,7 +881,7 @@ static int ltdc_get_caps(struct drm_device *ddev) >>> return 0; >>> } >>> >>> -static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) >>> +static struct drm_bridge *ltdc_get_bridge(struct drm_device *ddev) >>> { >>> struct device *dev = ddev->dev; >>> struct device_node *np = dev->of_node; >>> @@ -1004,7 +913,10 @@ static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) >>> } >>> } >>> >>> - return panel; >>> + if (!panel) >>> + return ERR_PTR(-ENODEV); >>> + >>> + return drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); >>> } >>> >>> int ltdc_load(struct drm_device *ddev) >>> @@ -1014,7 +926,6 @@ int ltdc_load(struct drm_device *ddev) >>> struct device *dev = ddev->dev; >>> struct device_node *np = dev->of_node; >>> struct drm_encoder *encoder; >>> - struct drm_connector *connector = NULL; >>> struct drm_crtc *crtc; >>> struct reset_control *rstc; >>> struct resource res; >>> @@ -1022,8 +933,8 @@ int ltdc_load(struct drm_device *ddev) >>> >>> DRM_DEBUG_DRIVER("\n"); >>> >>> - ldev->panel = ltdc_get_panel(ddev); >>> - if (!ldev->panel) >>> + ldev->bridge = ltdc_get_bridge(ddev); >>> + if (!ldev->bridge) >>> return -EPROBE_DEFER; >>> >>> rstc = of_reset_control_get(np, NULL); >>> @@ -1082,28 +993,13 @@ int ltdc_load(struct drm_device *ddev) >>> >>> DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); >>> >>> - if (ldev->panel) { >>> + if (ldev->bridge) { >>> encoder = ltdc_rgb_encoder_create(ddev); >>> if (!encoder) { >>> DRM_ERROR("Failed to create RGB encoder\n"); >>> ret = -EINVAL; >>> goto err; >>> } >>> - >>> - connector = ltdc_rgb_connector_create(ddev); >>> - if (!connector) { >>> - DRM_ERROR("Failed to create RGB connector\n"); >>> - ret = -EINVAL; >>> - goto err; >>> - } >>> - >>> - ret = drm_mode_connector_attach_encoder(connector, encoder); >>> - if (ret) { >>> - DRM_ERROR("Failed to attach connector to encoder\n"); >>> - goto err; >>> - } >>> - >>> - drm_panel_attach(ldev->panel, connector); >>> } >>> >>> crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); >>> @@ -1130,8 +1026,8 @@ int ltdc_load(struct drm_device *ddev) >>> >>> return 0; >>> err: >>> - if (ldev->panel) >>> - drm_panel_detach(ldev->panel); >>> + if (ldev->bridge) >>> + drm_panel_bridge_remove(ldev->bridge); >>> >>> clk_disable_unprepare(ldev->pixel_clk); >>> >>> @@ -1146,8 +1042,8 @@ void ltdc_unload(struct drm_device *ddev) >>> >>> drm_vblank_cleanup(ddev); >>> >>> - if (ldev->panel) >>> - drm_panel_detach(ldev->panel); >>> + if (ldev->bridge) >>> + drm_panel_bridge_remove(ldev->bridge); >>> >>> clk_disable_unprepare(ldev->pixel_clk); >>> } >>> diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h >>> index d7a9c736ac1e..d78cb0dd3200 100644 >>> --- a/drivers/gpu/drm/stm/ltdc.h >>> +++ b/drivers/gpu/drm/stm/ltdc.h >>> @@ -24,7 +24,7 @@ struct ltdc_device { >>> struct drm_fbdev_cma *fbdev; >>> void __iomem *regs; >>> struct clk *pixel_clk; /* lcd pixel clock */ >>> - struct drm_panel *panel; >>> + struct drm_bridge *bridge; >>> struct mutex err_lock; /* protecting error_status */ >>> struct ltdc_caps caps; >>> u32 clut[256]; /* color look up table */ >>> >
Hi Archit, Le Wed, 31 May 2017 13:31:16 +0530, Archit Taneja <architt@codeaurora.org> a écrit : > Hi Boris, > > On 05/31/2017 11:56 AM, Boris Brezillon wrote: > > Hi Philippe, > > > > Le Tue, 30 May 2017 16:55:42 +0000, > > Philippe CORNU <philippe.cornu@st.com> a écrit : > > > >> Hi Eric, > >> > >> I took your patch for the panel-bridge and it works perfectly in both > >> DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi), bravo :-) > > > > I still don't understand how it can work without a call to > > drm_bridge_attach() (which is used to link the RGB encoder to the DPI > > connector). I'm probably missing something obvious. Maybe someone can > > point it out :-). > > I think the expectation is that there will be a follow-up patch that > would add bridge support. Philippe had posted a patch for adding bridges > to ltdc before: > > https://patchwork.kernel.org/patch/9724835/ > > He can now redo his patch over Eric's panel-bridge patch-set. But by doing that you're breaking bisectability, or is it working when applying only Eric's patchset? If applying this patch breaks the driver, why not applying it after bridge support has been added to this driver? Regards, Boris
On 05/31/2017 01:37 PM, Boris Brezillon wrote: > Hi Archit, > > Le Wed, 31 May 2017 13:31:16 +0530, > Archit Taneja <architt@codeaurora.org> a écrit : > >> Hi Boris, >> >> On 05/31/2017 11:56 AM, Boris Brezillon wrote: >>> Hi Philippe, >>> >>> Le Tue, 30 May 2017 16:55:42 +0000, >>> Philippe CORNU <philippe.cornu@st.com> a écrit : >>> >>>> Hi Eric, >>>> >>>> I took your patch for the panel-bridge and it works perfectly in both >>>> DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi), bravo :-) >>> >>> I still don't understand how it can work without a call to >>> drm_bridge_attach() (which is used to link the RGB encoder to the DPI >>> connector). I'm probably missing something obvious. Maybe someone can >>> point it out :-). >> >> I think the expectation is that there will be a follow-up patch that >> would add bridge support. Philippe had posted a patch for adding bridges >> to ltdc before: >> >> https://patchwork.kernel.org/patch/9724835/ >> >> He can now redo his patch over Eric's panel-bridge patch-set. > > But by doing that you're breaking bisectability, or is it working when > applying only Eric's patchset? > > If applying this patch breaks the driver, why not applying it after > bridge support has been added to this driver? Yeah, it would break the driver. Philippe can create a patch that adds bridge support using the panel-bridge glue layer using Eric's patch as a reference. In the end, there should only be a single patch. Thanks, Archit > > Regards, > > Boris >
On 05/31/2017 10:35 AM, Archit Taneja wrote: > > > On 05/31/2017 01:37 PM, Boris Brezillon wrote: >> Hi Archit, >> >> Le Wed, 31 May 2017 13:31:16 +0530, >> Archit Taneja <architt@codeaurora.org> a écrit : >> >>> Hi Boris, >>> >>> On 05/31/2017 11:56 AM, Boris Brezillon wrote: >>>> Hi Philippe, >>>> >>>> Le Tue, 30 May 2017 16:55:42 +0000, >>>> Philippe CORNU <philippe.cornu@st.com> a écrit : >>>> >>>>> Hi Eric, >>>>> >>>>> I took your patch for the panel-bridge and it works perfectly in both >>>>> DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi), bravo :-) >>>> >>>> I still don't understand how it can work without a call to >>>> drm_bridge_attach() (which is used to link the RGB encoder to the DPI >>>> connector). I'm probably missing something obvious. Maybe someone can >>>> point it out :-). >>> >>> I think the expectation is that there will be a follow-up patch that >>> would add bridge support. Philippe had posted a patch for adding bridges >>> to ltdc before: >>> >>> https://patchwork.kernel.org/patch/9724835/ >>> >>> He can now redo his patch over Eric's panel-bridge patch-set. >> >> But by doing that you're breaking bisectability, or is it working when >> applying only Eric's patchset? >> >> If applying this patch breaks the driver, why not applying it after >> bridge support has been added to this driver? > > Yeah, it would break the driver. Philippe can create a patch that adds > bridge support using the panel-bridge glue layer using Eric's patch as a > reference. In the end, there should only be a single patch. > > Thanks, > Archit > >> >> Regards, >> >> Boris >> > Hi Boris & Archit, Sorry, I should have been clearer about what I did. Let me explain more below: 1 - I applied Eric's patch named "drm/bridge: Refactor out the panel wrapper from the lvds-encoder bridge" (https://lkml.org/lkml/2017/5/11/784) 2 - I did a patch on ltdc.c combining Eric's patch named "drm/ltdc: Use the panel-bridge helper" (https://lkml.org/lkml/2017/5/11/783) and my own preamble patch for STM32 DSI named "drm/stm: ltdc: Add bridge support" (https://patchwork.kernel.org/patch/9738427/) And tests are successful in both DPI mode (panel RGB //) and DSI mode (bridge dw mipi dsi). As suggested in the last Archit's email, there will be a single patch that will add bridge support to ltdc.c and I will send it in the "STM32 DSI HOST" v3 version, if you all agree of course :) Many thanks for all your great comments, Philippe
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index a40418cda74a..41a1c5d68f5b 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -269,11 +269,6 @@ static inline struct ltdc_device *encoder_to_ltdc(struct drm_encoder *enc) return (struct ltdc_device *)enc->dev->dev_private; } -static inline struct ltdc_device *connector_to_ltdc(struct drm_connector *con) -{ - return (struct ltdc_device *)con->dev->dev_private; -} - static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) { enum ltdc_pix_fmt pf; @@ -815,22 +810,12 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) static void ltdc_rgb_encoder_enable(struct drm_encoder *encoder) { - struct ltdc_device *ldev = encoder_to_ltdc(encoder); - DRM_DEBUG_DRIVER("\n"); - - drm_panel_prepare(ldev->panel); - drm_panel_enable(ldev->panel); } static void ltdc_rgb_encoder_disable(struct drm_encoder *encoder) { - struct ltdc_device *ldev = encoder_to_ltdc(encoder); - DRM_DEBUG_DRIVER("\n"); - - drm_panel_disable(ldev->panel); - drm_panel_unprepare(ldev->panel); } static const struct drm_encoder_helper_funcs ltdc_rgb_encoder_helper_funcs = { @@ -863,82 +848,6 @@ static struct drm_encoder *ltdc_rgb_encoder_create(struct drm_device *ddev) return encoder; } -/* - * DRM_CONNECTOR - */ - -static int ltdc_rgb_connector_get_modes(struct drm_connector *connector) -{ - struct drm_device *ddev = connector->dev; - struct ltdc_device *ldev = ddev->dev_private; - int ret = 0; - - DRM_DEBUG_DRIVER("\n"); - - if (ldev->panel) - ret = drm_panel_get_modes(ldev->panel); - - return ret < 0 ? 0 : ret; -} - -static struct drm_connector_helper_funcs ltdc_rgb_connector_helper_funcs = { - .get_modes = ltdc_rgb_connector_get_modes, -}; - -static enum drm_connector_status -ltdc_rgb_connector_detect(struct drm_connector *connector, bool force) -{ - struct ltdc_device *ldev = connector_to_ltdc(connector); - - return ldev->panel ? connector_status_connected : - connector_status_disconnected; -} - -static void ltdc_rgb_connector_destroy(struct drm_connector *connector) -{ - DRM_DEBUG_DRIVER("\n"); - - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static const struct drm_connector_funcs ltdc_rgb_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = ltdc_rgb_connector_detect, - .destroy = ltdc_rgb_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -struct drm_connector *ltdc_rgb_connector_create(struct drm_device *ddev) -{ - struct drm_connector *connector; - int err; - - connector = devm_kzalloc(ddev->dev, sizeof(*connector), GFP_KERNEL); - if (!connector) { - DRM_ERROR("Failed to allocate connector\n"); - return NULL; - } - - connector->polled = DRM_CONNECTOR_POLL_HPD; - - err = drm_connector_init(ddev, connector, <dc_rgb_connector_funcs, - DRM_MODE_CONNECTOR_DPI); - if (err) { - DRM_ERROR("Failed to initialize connector\n"); - return NULL; - } - - drm_connector_helper_add(connector, <dc_rgb_connector_helper_funcs); - - DRM_DEBUG_DRIVER("RGB connector:%d created\n", connector->base.id); - - return connector; -} - static int ltdc_get_caps(struct drm_device *ddev) { struct ltdc_device *ldev = ddev->dev_private; @@ -972,7 +881,7 @@ static int ltdc_get_caps(struct drm_device *ddev) return 0; } -static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) +static struct drm_bridge *ltdc_get_bridge(struct drm_device *ddev) { struct device *dev = ddev->dev; struct device_node *np = dev->of_node; @@ -1004,7 +913,10 @@ static struct drm_panel *ltdc_get_panel(struct drm_device *ddev) } } - return panel; + if (!panel) + return ERR_PTR(-ENODEV); + + return drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); } int ltdc_load(struct drm_device *ddev) @@ -1014,7 +926,6 @@ int ltdc_load(struct drm_device *ddev) struct device *dev = ddev->dev; struct device_node *np = dev->of_node; struct drm_encoder *encoder; - struct drm_connector *connector = NULL; struct drm_crtc *crtc; struct reset_control *rstc; struct resource res; @@ -1022,8 +933,8 @@ int ltdc_load(struct drm_device *ddev) DRM_DEBUG_DRIVER("\n"); - ldev->panel = ltdc_get_panel(ddev); - if (!ldev->panel) + ldev->bridge = ltdc_get_bridge(ddev); + if (!ldev->bridge) return -EPROBE_DEFER; rstc = of_reset_control_get(np, NULL); @@ -1082,28 +993,13 @@ int ltdc_load(struct drm_device *ddev) DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); - if (ldev->panel) { + if (ldev->bridge) { encoder = ltdc_rgb_encoder_create(ddev); if (!encoder) { DRM_ERROR("Failed to create RGB encoder\n"); ret = -EINVAL; goto err; } - - connector = ltdc_rgb_connector_create(ddev); - if (!connector) { - DRM_ERROR("Failed to create RGB connector\n"); - ret = -EINVAL; - goto err; - } - - ret = drm_mode_connector_attach_encoder(connector, encoder); - if (ret) { - DRM_ERROR("Failed to attach connector to encoder\n"); - goto err; - } - - drm_panel_attach(ldev->panel, connector); } crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); @@ -1130,8 +1026,8 @@ int ltdc_load(struct drm_device *ddev) return 0; err: - if (ldev->panel) - drm_panel_detach(ldev->panel); + if (ldev->bridge) + drm_panel_bridge_remove(ldev->bridge); clk_disable_unprepare(ldev->pixel_clk); @@ -1146,8 +1042,8 @@ void ltdc_unload(struct drm_device *ddev) drm_vblank_cleanup(ddev); - if (ldev->panel) - drm_panel_detach(ldev->panel); + if (ldev->bridge) + drm_panel_bridge_remove(ldev->bridge); clk_disable_unprepare(ldev->pixel_clk); } diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h index d7a9c736ac1e..d78cb0dd3200 100644 --- a/drivers/gpu/drm/stm/ltdc.h +++ b/drivers/gpu/drm/stm/ltdc.h @@ -24,7 +24,7 @@ struct ltdc_device { struct drm_fbdev_cma *fbdev; void __iomem *regs; struct clk *pixel_clk; /* lcd pixel clock */ - struct drm_panel *panel; + struct drm_bridge *bridge; struct mutex err_lock; /* protecting error_status */ struct ltdc_caps caps; u32 clut[256]; /* color look up table */
Another 100 lines of boilerplate gone. Bridges aren't supported yet, but will be trivial to add later. Signed-off-by: Eric Anholt <eric@anholt.net> --- Also untested. drivers/gpu/drm/stm/ltdc.c | 128 +++++---------------------------------------- drivers/gpu/drm/stm/ltdc.h | 2 +- 2 files changed, 13 insertions(+), 117 deletions(-)