@@ -55,6 +55,9 @@ to_drm_dp_typec_bridge_data(struct drm_bridge *bridge)
struct drm_dp_typec_bridge_dev {
struct auxiliary_device adev;
size_t max_lanes;
+ void (*hpd_notify)(struct drm_dp_typec_bridge_dev *dev,
+ void *data, enum drm_connector_status status);
+ void *hpd_data;
bool no_hpd;
};
@@ -235,6 +238,8 @@ devm_drm_dp_typec_bridge_alloc(struct device *parent, const struct drm_dp_typec_
adev->dev.platform_data = of_node_get(desc->of_node);
typec_bridge_dev->max_lanes = desc->num_dp_lanes;
typec_bridge_dev->no_hpd = desc->no_hpd;
+ typec_bridge_dev->hpd_notify = desc->hpd_notify;
+ typec_bridge_dev->hpd_data = desc->hpd_data;
ret = auxiliary_device_init(adev);
if (ret) {
@@ -305,6 +310,19 @@ void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev
}
EXPORT_SYMBOL_GPL(drm_dp_typec_bridge_notify);
+static void drm_dp_typec_bridge_hpd_notify(struct drm_bridge *bridge,
+ enum drm_connector_status status)
+{
+ struct drm_dp_typec_bridge_data *data;
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev;
+
+ data = to_drm_dp_typec_bridge_data(bridge);
+ typec_bridge_dev = to_drm_dp_typec_bridge_dev(data->hpd_bridge.dev);
+
+ if (typec_bridge_dev->hpd_notify)
+ typec_bridge_dev->hpd_notify(typec_bridge_dev, typec_bridge_dev->hpd_data, status);
+}
+
static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
@@ -460,6 +478,7 @@ static const struct drm_bridge_funcs drm_dp_typec_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .hpd_notify = drm_dp_typec_bridge_hpd_notify,
};
enum drm_aux_bridge_type {
@@ -28,11 +28,16 @@ struct drm_dp_typec_bridge_dev;
* struct drm_dp_typec_bridge_desc - drm_dp_typec_bridge descriptor
* @of_node: device node pointer corresponding to this bridge instance
* @num_dp_lanes: number of input DP lanes possible (1, 2 or 4)
+ * @hpd_notify: callback for bridge hot plug detect events
+ * @hpd_data: data passed to @hpd_notify callback
* @no_hpd: true if this bridge can't signal HPD state with drm_dp_typec_bridge_notify()
*/
struct drm_dp_typec_bridge_desc {
struct device_node *of_node;
size_t num_dp_lanes;
+ void (*hpd_notify)(struct drm_dp_typec_bridge_dev *typec_bridge_dev,
+ void *data, enum drm_connector_status status);
+ void *hpd_data;
bool no_hpd;
};
The previous patch added support for no-hpd to drm_dp_typec_bridge code. Allow users of this bridge to hook the HPD notification path of the bridge chain so that they can be made aware of the connector status changing. This helps HPD-less users of the bridge inject the HPD state into their code by using the connector status as a proxy for HPD being asserted or deasserted. In particular, this will help Trogdor/Strongbad boards that need to read the EC's analog mux which steers the DP signal to one or the other USB type-c ports to figure out which type-c port has HPD asserted. Cc: Prashant Malani <pmalani@chromium.org> Cc: Benson Leung <bleung@chromium.org> Cc: Tzung-Bi Shih <tzungbi@kernel.org> Cc: <chrome-platform@lists.linux.dev> Cc: Pin-yen Lin <treapking@chromium.org> Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Signed-off-by: Stephen Boyd <swboyd@chromium.org> --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 19 +++++++++++++++++++ include/drm/bridge/aux-bridge.h | 5 +++++ 2 files changed, 24 insertions(+)