To support the upcoming DRM bridge hotplug, the drm_bridge.c code will need to call drm_atomic_helper_shutdown() to disable the pipeline when the tail bridges of the pipeline are removed without tearing down the card.
However this would create a module dependency loop between the drm module (where drm_encoder is) and the drm_kms_helper module where drm_atomic_helper_shutdown() function currently is and which already depends on the drm module. Solve by moving drm_atomic_helper_shutdown(), along with its callee drm_atomic_helper_disable_all(), to drm_atomic which is in the drm module. Use identical names except for dropping the "_helper" infix, and make the original functions a deprecated wrapper to the new ones. No changes to the functions body. No functional changes except for moving the code to a different module. Signed-off-by: Luca Ceresoli <[email protected]> --- drivers/gpu/drm/drm_atomic.c | 115 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 76 ++---------------------- include/drm/drm_atomic.h | 3 + 3 files changed, 124 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9b2009262c97..7d12c062c16d 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1993,6 +1993,121 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, } EXPORT_SYMBOL(__drm_atomic_helper_set_config); +/** + * drm_atomic_disable_all - disable all currently active outputs + * @dev: DRM device + * @ctx: lock acquisition context + * + * Loops through all connectors, finding those that aren't turned off and then + * turns them off by setting their DPMS mode to OFF and deactivating the CRTC + * that they are connected to. + * + * This is used for example in suspend/resume to disable all currently active + * functions when suspending. If you just want to shut down everything at e.g. + * driver unload, look at drm_atomic_helper_shutdown(). + * + * Note that if callers haven't already acquired all modeset locks this might + * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). + * + * Returns: + * 0 on success or a negative error code on failure. + * + * See also: + * drm_atomic_helper_suspend(), drm_atomic_helper_resume() and + * drm_atomic_helper_shutdown(). + */ +int drm_atomic_disable_all(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_commit *state; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + struct drm_plane_state *plane_state; + struct drm_plane *plane; + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + int ret, i; + + state = drm_atomic_commit_alloc(dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = ctx; + + drm_for_each_crtc(crtc, dev) { + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto free; + } + + crtc_state->active = false; + + ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, NULL); + if (ret < 0) + goto free; + + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret < 0) + goto free; + + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret < 0) + goto free; + } + + for_each_new_connector_in_state(state, conn, conn_state, i) { + ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); + if (ret < 0) + goto free; + } + + for_each_new_plane_in_state(state, plane, plane_state, i) { + ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); + if (ret < 0) + goto free; + + drm_atomic_set_fb_for_plane(plane_state, NULL); + } + + ret = drm_atomic_commit(state); +free: + drm_atomic_commit_put(state); + return ret; +} +EXPORT_SYMBOL(drm_atomic_disable_all); + +/** + * drm_atomic_shutdown - shutdown all CRTC + * @dev: DRM device + * + * This shuts down all CRTC, which is useful for driver unloading. Shutdown on + * suspend should instead be handled with drm_atomic_helper_suspend(), since + * that also takes a snapshot of the modeset state to be restored on resume. + * + * This is just a convenience wrapper around drm_atomic_helper_disable_all(), + * and it is the atomic version of drm_helper_force_disable_all(). + */ +void drm_atomic_shutdown(struct drm_device *dev) +{ + struct drm_modeset_acquire_ctx ctx; + int ret; + + if (dev == NULL) + return; + + DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); + + ret = drm_atomic_disable_all(dev, &ctx); + if (ret) + drm_err(dev, + "Disabling all crtc's during unload failed with %i\n", + ret); + + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); +} +EXPORT_SYMBOL(drm_atomic_shutdown); + static void drm_atomic_private_obj_print_state(struct drm_printer *p, const struct drm_private_state *state) { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 51f39edc31ed..afedfab9b568 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3533,6 +3533,8 @@ EXPORT_SYMBOL(drm_atomic_helper_set_config); * @dev: DRM device * @ctx: lock acquisition context * + * Deprecated wrapper to drm_atomic_disable_all(). + * * Loops through all connectors, finding those that aren't turned off and then * turns them off by setting their DPMS mode to OFF and deactivating the CRTC * that they are connected to. @@ -3554,61 +3556,7 @@ EXPORT_SYMBOL(drm_atomic_helper_set_config); int drm_atomic_helper_disable_all(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx) { - struct drm_atomic_commit *state; - struct drm_connector_state *conn_state; - struct drm_connector *conn; - struct drm_plane_state *plane_state; - struct drm_plane *plane; - struct drm_crtc_state *crtc_state; - struct drm_crtc *crtc; - int ret, i; - - state = drm_atomic_commit_alloc(dev); - if (!state) - return -ENOMEM; - - state->acquire_ctx = ctx; - - drm_for_each_crtc(crtc, dev) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - goto free; - } - - crtc_state->active = false; - - ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, NULL); - if (ret < 0) - goto free; - - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret < 0) - goto free; - - ret = drm_atomic_add_affected_connectors(state, crtc); - if (ret < 0) - goto free; - } - - for_each_new_connector_in_state(state, conn, conn_state, i) { - ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); - if (ret < 0) - goto free; - } - - for_each_new_plane_in_state(state, plane, plane_state, i) { - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); - if (ret < 0) - goto free; - - drm_atomic_set_fb_for_plane(plane_state, NULL); - } - - ret = drm_atomic_commit(state); -free: - drm_atomic_commit_put(state); - return ret; + return drm_atomic_disable_all(dev, ctx); } EXPORT_SYMBOL(drm_atomic_helper_disable_all); @@ -3664,6 +3612,8 @@ EXPORT_SYMBOL(drm_atomic_helper_reset_crtc); * drm_atomic_helper_shutdown - shutdown all CRTC * @dev: DRM device * + * Deprecated wrapper to drm_atomic_shutdown(). + * * This shuts down all CRTC, which is useful for driver unloading. Shutdown on * suspend should instead be handled with drm_atomic_helper_suspend(), since * that also takes a snapshot of the modeset state to be restored on resume. @@ -3673,21 +3623,7 @@ EXPORT_SYMBOL(drm_atomic_helper_reset_crtc); */ void drm_atomic_helper_shutdown(struct drm_device *dev) { - struct drm_modeset_acquire_ctx ctx; - int ret; - - if (dev == NULL) - return; - - DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); - - ret = drm_atomic_helper_disable_all(dev, &ctx); - if (ret) - drm_err(dev, - "Disabling all crtc's during unload failed with %i\n", - ret); - - DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); + return drm_atomic_shutdown(dev); } EXPORT_SYMBOL(drm_atomic_helper_shutdown); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 1a80a8cdf269..9eb3d1bfa084 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -1373,5 +1373,8 @@ drm_atomic_get_old_bridge_state(const struct drm_atomic_commit *state, struct drm_bridge_state * drm_atomic_get_new_bridge_state(const struct drm_atomic_commit *state, struct drm_bridge *bridge); +int drm_atomic_disable_all(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx); +void drm_atomic_shutdown(struct drm_device *dev); #endif /* DRM_ATOMIC_H_ */ -- 2.54.0
