[PATCH RFC 1/6] drm/bridge: add setup_connector callback

Dmitry Baryshkov dmitry.baryshkov at linaro.org
Thu Mar 7 23:57:00 UTC 2024


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.baryshkov at 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



More information about the Freedreno mailing list