From: Noralf Trønnes Date: Mon, 6 Nov 2017 19:18:08 +0000 (+0100) Subject: drm/modeset-helper: Add simple modeset suspend/resume helpers X-Git-Tag: v5.15~8118^2~45^2~704 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ca038cfb5cfa8d48b427b916efe97e711f5a18c7;p=platform%2Fkernel%2Flinux-starfive.git drm/modeset-helper: Add simple modeset suspend/resume helpers Add drm_mode_config_helper_suspend/resume() which takes care of atomic modeset suspend/resume for simple use cases. The suspend state is stored in struct drm_mode_config. Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171106191812.38927-3-noralf@tronnes.org --- diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 9cb1eed..f1c24ab 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -20,6 +20,9 @@ * OF THIS SOFTWARE. */ +#include +#include +#include #include #include @@ -156,3 +159,76 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, NULL); } EXPORT_SYMBOL(drm_crtc_init); + +/** + * drm_mode_config_helper_suspend - Modeset suspend helper + * @dev: DRM device + * + * This helper function takes care of suspending the modeset side. It disables + * output polling if initialized, suspends fbdev if used and finally calls + * drm_atomic_helper_suspend(). + * If suspending fails, fbdev and polling is re-enabled. + * + * Returns: + * Zero on success, negative error code on error. + * + * See also: + * drm_kms_helper_poll_disable() and drm_fb_helper_set_suspend_unlocked(). + */ +int drm_mode_config_helper_suspend(struct drm_device *dev) +{ + struct drm_atomic_state *state; + + if (!dev) + return 0; + + drm_kms_helper_poll_disable(dev); + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1); + state = drm_atomic_helper_suspend(dev); + if (IS_ERR(state)) { + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0); + drm_kms_helper_poll_enable(dev); + return PTR_ERR(state); + } + + dev->mode_config.suspend_state = state; + + return 0; +} +EXPORT_SYMBOL(drm_mode_config_helper_suspend); + +/** + * drm_mode_config_helper_resume - Modeset resume helper + * @dev: DRM device + * + * This helper function takes care of resuming the modeset side. It calls + * drm_atomic_helper_resume(), resumes fbdev if used and enables output polling + * if initiaized. + * + * Returns: + * Zero on success, negative error code on error. + * + * See also: + * drm_fb_helper_set_suspend_unlocked() and drm_kms_helper_poll_enable(). + */ +int drm_mode_config_helper_resume(struct drm_device *dev) +{ + int ret; + + if (!dev) + return 0; + + if (WARN_ON(!dev->mode_config.suspend_state)) + return -EINVAL; + + ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state); + if (ret) + DRM_ERROR("Failed to resume (%d)\n", ret); + dev->mode_config.suspend_state = NULL; + + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0); + drm_kms_helper_poll_enable(dev); + + return ret; +} +EXPORT_SYMBOL(drm_mode_config_helper_resume); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index cf73c5e..eb3b8db 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -753,6 +753,15 @@ struct drm_mode_config { /* cursor size */ uint32_t cursor_width, cursor_height; + /** + * @suspend_state: + * + * Atomic state when suspended. + * Set by drm_mode_config_helper_suspend() and cleared by + * drm_mode_config_helper_resume(). + */ + struct drm_atomic_state *suspend_state; + const struct drm_mode_config_helper_funcs *helper_private; }; diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h index cb0ec92..efa337f 100644 --- a/include/drm/drm_modeset_helper.h +++ b/include/drm/drm_modeset_helper.h @@ -34,4 +34,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs); +int drm_mode_config_helper_suspend(struct drm_device *dev); +int drm_mode_config_helper_resume(struct drm_device *dev); + #endif