Let's provide an helper to make it easier for bridge drivers to power-cycle their bridge. Co-developed-by: Simona Vetter <simona.vetter@xxxxxxxx> Signed-off-by: Maxime Ripard <mripard@xxxxxxxxxx> --- drivers/gpu/drm/drm_bridge.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 8241c00e4506eceeb9bb4ba74a38d8f360c65d38..ca894531a2042fc9296c40a1f51a6cdea6e97ed7 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -24,10 +24,11 @@ #include <linux/err.h> #include <linux/media-bus-format.h> #include <linux/module.h> #include <linux/mutex.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_debugfs.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> @@ -1269,10 +1270,53 @@ void drm_bridge_hpd_notify(struct drm_bridge *bridge, bridge->hpd_cb(bridge->hpd_data, status); mutex_unlock(&bridge->hpd_mutex); } EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify); +/** + * drm_bridge_reset_crtc - Reset the pipeline feeding a bridge + * @bridge: DRM bridge to reset + * @ctx: lock acquisition context + * + * Reset a @bridge pipeline. It will power-cycle all active components + * between the CRTC and connector that bridge is connected to. + * + * Returns: + * + * 0 on success or a negative error code on failure. If the error + * returned is EDEADLK, the whole atomic sequence must be restarted. + */ +int drm_bridge_reset_crtc(struct drm_bridge *bridge, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_connector *connector; + struct drm_encoder *encoder = bridge->encoder; + struct drm_device *dev = encoder->dev; + struct drm_crtc *crtc; + int ret; + + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx); + if (ret) + return ret; + + connector = drm_atomic_get_connector_for_encoder(encoder, ctx); + if (IS_ERR(connector)) { + ret = PTR_ERR(connector); + goto out; + } + + crtc = connector->state->crtc; + ret = drm_atomic_helper_reset_crtc(crtc, ctx); + if (ret) + goto out; + +out: + drm_modeset_unlock(&dev->mode_config.connection_mutex); + return ret; +} +EXPORT_SYMBOL(drm_bridge_reset_crtc); + #ifdef CONFIG_OF /** * of_drm_find_bridge - find the bridge corresponding to the device node in * the global bridge list * diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 6fb1da7c195e99143a67a999d16fe361c1e3f4ab..32169e62463bb268a281a5903c0c9f448a1042b3 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1085,10 +1085,12 @@ void drm_bridge_hpd_enable(struct drm_bridge *bridge, enum drm_connector_status status), void *data); void drm_bridge_hpd_disable(struct drm_bridge *bridge); void drm_bridge_hpd_notify(struct drm_bridge *bridge, enum drm_connector_status status); +int drm_bridge_reset_crtc(struct drm_bridge *bridge, + struct drm_modeset_acquire_ctx *ctx); #ifdef CONFIG_DRM_PANEL_BRIDGE bool drm_bridge_is_panel(const struct drm_bridge *bridge); struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel); struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, -- 2.48.1