W dniu 23.09.2021 o 02:29, Laurent Pinchart pisze: > 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. When drm_panel_bridge was proposed 1st time I suggested that instead of it we should just merge panels with bridges (maybe with new name, my favorite is drm_sink), but I was outvoted :) Apparently with this patch we go to the same direction: since panels will be accessed only via drm_panel_bridge they will become actually bridges :) Somebody could then clean-up the whole intermediate code. Regards Andrzej > > 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 >>