Message ID | 20250225-bridge-connector-v4-7-7ecb07b09cad@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | drm/bridge: Various quality of life improvements | expand |
On Tue, Feb 25, 2025 at 05:43:55PM +0100, Maxime Ripard wrote: > Let's provide an helper to make it easier for bridge drivers to > power-cycle their bridge. > > Co-developed-by: Simona Vetter <simona.vetter@ffwll.ch> > Signed-off-by: Maxime Ripard <mripard@kernel.org> > --- > 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; > + } > + Should there be a check for connector->state before accessing connector->state->crtc ? > + 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 >
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,
Let's provide an helper to make it easier for bridge drivers to power-cycle their bridge. Co-developed-by: Simona Vetter <simona.vetter@ffwll.ch> Signed-off-by: Maxime Ripard <mripard@kernel.org> --- drivers/gpu/drm/drm_bridge.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 2 ++ 2 files changed, 46 insertions(+)