Commit 986c58d1 authored by Thierry Reding's avatar Thierry Reding

drm/tegra: Implement subsystem-level suspend/resume

Use the drm_atomic_helper_suspend() and drm_atomic_helper_resume()
helpers to implement subsystem-level suspend/resume.

v2: suspend framebuffer device to avoid concurrency issues
v3: resume fbdev on failure to suspend (Emil Velikov)
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 01b9bea0
...@@ -1021,8 +1021,17 @@ static int host1x_drm_remove(struct host1x_device *dev) ...@@ -1021,8 +1021,17 @@ static int host1x_drm_remove(struct host1x_device *dev)
static int host1x_drm_suspend(struct device *dev) static int host1x_drm_suspend(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
struct tegra_drm *tegra = drm->dev_private;
drm_kms_helper_poll_disable(drm); drm_kms_helper_poll_disable(drm);
tegra_drm_fb_suspend(drm);
tegra->state = drm_atomic_helper_suspend(drm);
if (IS_ERR(tegra->state)) {
tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);
return PTR_ERR(tegra->state);
}
return 0; return 0;
} }
...@@ -1030,7 +1039,10 @@ static int host1x_drm_suspend(struct device *dev) ...@@ -1030,7 +1039,10 @@ static int host1x_drm_suspend(struct device *dev)
static int host1x_drm_resume(struct device *dev) static int host1x_drm_resume(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
struct tegra_drm *tegra = drm->dev_private;
drm_atomic_helper_resume(drm, tegra->state);
tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm); drm_kms_helper_poll_enable(drm);
return 0; return 0;
......
...@@ -57,6 +57,8 @@ struct tegra_drm { ...@@ -57,6 +57,8 @@ struct tegra_drm {
struct work_struct work; struct work_struct work;
struct mutex lock; struct mutex lock;
} commit; } commit;
struct drm_atomic_state *state;
}; };
struct tegra_drm_client; struct tegra_drm_client;
...@@ -272,6 +274,8 @@ int tegra_drm_fb_prepare(struct drm_device *drm); ...@@ -272,6 +274,8 @@ int tegra_drm_fb_prepare(struct drm_device *drm);
void tegra_drm_fb_free(struct drm_device *drm); void tegra_drm_fb_free(struct drm_device *drm);
int tegra_drm_fb_init(struct drm_device *drm); int tegra_drm_fb_init(struct drm_device *drm);
void tegra_drm_fb_exit(struct drm_device *drm); void tegra_drm_fb_exit(struct drm_device *drm);
void tegra_drm_fb_suspend(struct drm_device *drm);
void tegra_drm_fb_resume(struct drm_device *drm);
#ifdef CONFIG_DRM_FBDEV_EMULATION #ifdef CONFIG_DRM_FBDEV_EMULATION
void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
void tegra_fb_output_poll_changed(struct drm_device *drm); void tegra_fb_output_poll_changed(struct drm_device *drm);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/console.h>
#include "drm.h" #include "drm.h"
#include "gem.h" #include "gem.h"
...@@ -413,3 +415,25 @@ void tegra_drm_fb_exit(struct drm_device *drm) ...@@ -413,3 +415,25 @@ void tegra_drm_fb_exit(struct drm_device *drm)
tegra_fbdev_exit(tegra->fbdev); tegra_fbdev_exit(tegra->fbdev);
#endif #endif
} }
void tegra_drm_fb_suspend(struct drm_device *drm)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
console_lock();
drm_fb_helper_set_suspend(&tegra->fbdev->base, 1);
console_unlock();
#endif
}
void tegra_drm_fb_resume(struct drm_device *drm)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
console_lock();
drm_fb_helper_set_suspend(&tegra->fbdev->base, 0);
console_unlock();
#endif
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment