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

Reply via email to