Add a callback to be called by the drivers when the drm_connector is
created at the end of the drm_bridge chain. This allows bridges to
perform additional setup, like setting up the HDMI connector properties.

Note, for now only drm_bridge_connector uses this callback.

Signed-off-by: Dmitry Baryshkov <dmitry.barysh...@linaro.org>
---
 drivers/gpu/drm/drm_bridge.c           | 38 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_bridge_connector.c |  8 +++++++
 include/drm/drm_bridge.h               | 15 ++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 521a71c61b16..375982a02bcf 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -580,6 +580,44 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_set);
 
+/**
+ * drm_bridge_chain_setup_connector - call all bridges to perform additional 
setup
+ *                                    of the attached drm_connector
+ * @bridge: bridge control structure
+ * @connector: connector that is used at the end of the bridge chain
+ *
+ * Calls &drm_bridge_funcs.setup_connector for all the bridges in the encoder
+ * chain, starting from the first bridge to the last. If at least one bridge
+ * does not accept the connector the function returns the error code.
+ *
+ * Note: the bridge passed should be the one closest to the encoder.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+int drm_bridge_chain_setup_connector(struct drm_bridge *bridge,
+                                    struct drm_connector *connector)
+{
+       struct drm_encoder *encoder;
+       int ret;
+
+       if (!bridge)
+               return 0;
+
+       encoder = bridge->encoder;
+       list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+               if (!bridge->funcs->setup_connector)
+                       continue;
+
+               ret = bridge->funcs->setup_connector(bridge, connector);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_bridge_chain_setup_connector);
+
 /**
  * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
index 982552c9f92c..a0d0d2cc72c7 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -402,6 +402,14 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
        if (panel_bridge)
                drm_panel_bridge_set_orientation(connector, panel_bridge);
 
+       ret = 
drm_bridge_chain_setup_connector(drm_bridge_chain_get_first_bridge(encoder),
+                                              connector);
+       if (ret) {
+               drm_connector_cleanup(connector);
+               kfree(bridge_connector);
+               return ERR_PTR(ret);
+       }
+
        return connector;
 }
 EXPORT_SYMBOL_GPL(drm_bridge_connector_init);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 3606e1a7f965..9806fce126f2 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -84,6 +84,19 @@ struct drm_bridge_funcs {
         */
        void (*detach)(struct drm_bridge *bridge);
 
+       /**
+        * @setup_connector:
+        *
+        * Perform additional setup of the connector once it is created.
+        *
+        * The @setup_connector callback is optional.
+        *
+        * RETURNS:
+        *
+        * Zero on success, error code on failure.
+        */
+       int (*setup_connector)(struct drm_bridge *bridge, struct drm_connector 
*connector);
+
        /**
         * @mode_valid:
         *
@@ -877,6 +890,8 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge 
*bridge,
                                        struct drm_atomic_state *state);
 void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
                                    struct drm_atomic_state *state);
+int drm_bridge_chain_setup_connector(struct drm_bridge *bridge,
+                                    struct drm_connector *connector);
 
 u32 *
 drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,

-- 
2.39.2

Reply via email to