Blob Blame History Raw
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Mon, 6 Nov 2017 20:18:08 +0100
Subject: drm/modeset-helper: Add simple modeset suspend/resume helpers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: ca038cfb5cfa8d48b427b916efe97e711f5a18c7
Patch-mainline: v4.16-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

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 <noralf@tronnes.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20171106191812.38927-3-noralf@tronnes.org

Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/drm_modeset_helper.c |   76 +++++++++++++++++++++++++++++++++++
 include/drm/drm_mode_config.h        |    9 ++++
 include/drm/drm_modeset_helper.h     |    3 +
 3 files changed, 88 insertions(+)

--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -20,6 +20,9 @@
  * OF THIS SOFTWARE.
  */
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_plane_helper.h>
 
@@ -156,3 +159,76 @@ int drm_crtc_init(struct drm_device *dev
 					 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);
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -776,6 +776,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;
 };
 
--- 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(stru
 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