Hi Maxime, Thank you for the patch. I know this has already been merged, but I have a question. On Fri, Sep 10, 2021 at 03:09:39PM +0200, Maxime Ripard wrote: > Display drivers so far need to have a lot of boilerplate to first > retrieve either the panel or bridge that they are connected to using > drm_of_find_panel_or_bridge(), and then either deal with each with ad-hoc > functions or create a drm panel bridge through drm_panel_bridge_add. > > In order to reduce the boilerplate and hopefully create a path of least > resistance towards using the DRM panel bridge layer, let's create the > function devm_drm_of_get_next to reduce that boilerplate. > > Signed-off-by: Maxime Ripard <maxime@xxxxxxxxxx> > --- > drivers/gpu/drm/drm_bridge.c | 42 ++++++++++++++++++++++++++++++++---- > drivers/gpu/drm/drm_of.c | 3 +++ > include/drm/drm_bridge.h | 2 ++ > 3 files changed, 43 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c > index a8ed66751c2d..10ddca4638b0 100644 > --- a/drivers/gpu/drm/drm_bridge.c > +++ b/drivers/gpu/drm/drm_bridge.c > @@ -28,6 +28,7 @@ > #include <drm/drm_atomic_state_helper.h> > #include <drm/drm_bridge.h> > #include <drm/drm_encoder.h> > +#include <drm/drm_of.h> > #include <drm/drm_print.h> > > #include "drm_crtc_internal.h" > @@ -51,10 +52,8 @@ > * > * Display drivers are responsible for linking encoders with the first bridge > * in the chains. This is done by acquiring the appropriate bridge with > - * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a > - * panel with drm_panel_bridge_add_typed() (or the managed version > - * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be > - * attached to the encoder with a call to drm_bridge_attach(). > + * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to the > + * encoder with a call to drm_bridge_attach(). > * > * Bridges are responsible for linking themselves with the next bridge in the > * chain, if any. This is done the same way as for encoders, with the call to > @@ -1233,6 +1232,41 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np) > return NULL; > } > EXPORT_SYMBOL(of_drm_find_bridge); > + > +/** > + * devm_drm_of_get_bridge - Return next bridge in the chain > + * @dev: device to tie the bridge lifetime to > + * @np: device tree node containing encoder output ports > + * @port: port in the device tree node > + * @endpoint: endpoint in the device tree node > + * > + * Given a DT node's port and endpoint number, finds the connected node > + * and returns the associated bridge if any, or creates and returns a > + * drm panel bridge instance if a panel is connected. > + * > + * Returns a pointer to the bridge if successful, or an error pointer > + * otherwise. > + */ > +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, > + struct device_node *np, > + unsigned int port, > + unsigned int endpoint) > +{ > + struct drm_bridge *bridge; > + struct drm_panel *panel; > + int ret; > + > + ret = drm_of_find_panel_or_bridge(np, port, endpoint, > + &panel, &bridge); > + if (ret) > + return ERR_PTR(ret); > + > + if (panel) > + bridge = devm_drm_panel_bridge_add(dev, panel); > + > + return bridge; I really like the idea, I've wanted to do something like this for a long time. I however wonder if this is the best approach, or if we could get the panel core to register the bridge itself. The part that bothers me here is the assymetry in the lifetime of the bridges, the returned pointer is either looked up or allocated. Bridge lifetime is such a mess that it may not make a big difference, but eventually we'll have to address that problem globally. > +} > +EXPORT_SYMBOL(devm_drm_of_get_bridge); > #endif > > MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@xxxxxxxxxxx>"); > diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c > index 997b8827fed2..37c34146eea8 100644 > --- a/drivers/gpu/drm/drm_of.c > +++ b/drivers/gpu/drm/drm_of.c > @@ -231,6 +231,9 @@ EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); > * return either the associated struct drm_panel or drm_bridge device. Either > * @panel or @bridge must not be NULL. > * > + * This function is deprecated and should not be used in new drivers. Use > + * devm_drm_of_get_bridge() instead. > + * > * Returns zero if successful, or one of the standard error codes if it fails. > */ > int drm_of_find_panel_or_bridge(const struct device_node *np, > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h > index 46bdfa48c413..f70c88ca96ef 100644 > --- a/include/drm/drm_bridge.h > +++ b/include/drm/drm_bridge.h > @@ -911,6 +911,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev, > struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, > struct drm_panel *panel, > u32 connector_type); > +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node *node, > + unsigned int port, unsigned int endpoint); > struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge); > #endif > -- Regards, Laurent Pinchart