A bridge has no way to take part in setting up the connector created for its chain. Whatever a bridge needs on the connector ends up special-cased in the code creating it: drm_bridge_connector looks for a panel bridge in order to set the panel orientation and checks the dedicated drm_bridge.support_hdcp flag to attach the content protection property, the msm DP driver attaches the DP subconnector property after creating the bridge connector. A DP bridge which is not a part of the display driver cannot get the DP properties attached at all.
Add an optional callback for that and a function calling it for the whole chain. The function is separate from drm_bridge_connector, so that the drivers creating the connector on their own can use it too. Only the panel orientation is going to be converted for now, support_hdcp and the DP properties are left for later. Assisted-by: LLM Signed-off-by: Dmitry Baryshkov <[email protected]> --- drivers/gpu/drm/drm_bridge.c | 31 +++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 23 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index e7f9e6d58927..10c8388594a3 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -846,6 +846,37 @@ void drm_bridge_chain_mode_set(struct drm_bridge *first_bridge, } EXPORT_SYMBOL(drm_bridge_chain_mode_set); +/** + * drm_bridge_chain_connector_init - let the bridges set up a connector + * @encoder: encoder the connector has been created for + * @connector: the connector + * + * Calls &drm_bridge_funcs.connector_init for all the bridges in the encoder + * chain, starting from the first bridge to the last. It should be called by + * the code creating a connector for the chain, after the connector has been + * initialized and before it is registered. + * + * RETURNS: + * 0 on success, a negative error code on failure + */ +int drm_bridge_chain_connector_init(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + drm_for_each_bridge_in_chain(encoder, bridge) { + int ret; + + if (!bridge->funcs->connector_init) + continue; + + ret = bridge->funcs->connector_init(bridge, connector); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(drm_bridge_chain_connector_init); + /** * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain * @bridge: bridge control structure diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 1981d24a700d..470b9c6cb12a 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -881,6 +881,27 @@ struct drm_bridge_funcs { struct drm_connector *connector, bool enable, int direction); + /** + * @connector_init: + * + * Called when a connector is created for the encoder chain containing + * this bridge, before the connector is registered. This lets the bridge + * set up the parts of the connector it knows about, e.g. attach + * properties. + * + * The callback is invoked through drm_bridge_chain_connector_init(), + * it is not tied to the bridge being the last one in the chain or to + * the &drm_bridge.ops of the bridge. The bridge chain is locked while + * it runs, so it must not attach or detach bridges. + * + * This callback is optional. + * + * Returns: + * 0 on success, a negative error code otherwise + */ + int (*connector_init)(struct drm_bridge *bridge, + struct drm_connector *connector); + /** * @debugfs_init: * @@ -1484,6 +1505,8 @@ enum drm_mode_status drm_bridge_chain_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode); +int drm_bridge_chain_connector_init(struct drm_encoder *encoder, + struct drm_connector *connector); void drm_bridge_chain_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode); -- 2.47.3
