aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2015-10-02 04:10:42 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2016-03-03 10:38:20 -0500
commit92bf0f9e2a9f1ea99d86ab6b0c3a87183a67e63c (patch)
tree07dd215fe2d33e68f2f8f82866e8c85c0cf5babc /drivers/gpu/drm/omapdrm
parentbfeece553335f9b9bf0d4dc9ea8a602a2248dfd6 (diff)
drm/omap: fix suspend/resume handling
For legacy reasons omapdss handles system suspend/resume via PM notifier callback, where the driver disables/resumes all the outputs. This doesn't work well with omapdrm. What happens on suspend is that the omapdss disables the displays while omapdrm is still happily continuing its work, possibly waiting for an vsync irq, which will never come if the display output is disabled, leading to timeouts and errors sent to userspace. This patch moves the suspend/resume handling to omapdrm, and the suspend/resume is now done safely inside modeset lock. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/core.c29
-rw-r--r--drivers/gpu/drm/omapdrm/dss/display.c36
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.h2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c44
4 files changed, 44 insertions, 67 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/core.c b/drivers/gpu/drm/omapdrm/dss/core.c
index 54eeb507f9b3..1f55d0aae03d 100644
--- a/drivers/gpu/drm/omapdrm/dss/core.c
+++ b/drivers/gpu/drm/omapdrm/dss/core.c
@@ -165,31 +165,6 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
165#endif /* CONFIG_OMAP2_DSS_DEBUGFS */ 165#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
166 166
167/* PLATFORM DEVICE */ 167/* PLATFORM DEVICE */
168static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
169{
170 DSSDBG("pm notif %lu\n", v);
171
172 switch (v) {
173 case PM_SUSPEND_PREPARE:
174 case PM_HIBERNATION_PREPARE:
175 case PM_RESTORE_PREPARE:
176 DSSDBG("suspending displays\n");
177 return dss_suspend_all_devices();
178
179 case PM_POST_SUSPEND:
180 case PM_POST_HIBERNATION:
181 case PM_POST_RESTORE:
182 DSSDBG("resuming displays\n");
183 return dss_resume_all_devices();
184
185 default:
186 return 0;
187 }
188}
189
190static struct notifier_block omap_dss_pm_notif_block = {
191 .notifier_call = omap_dss_pm_notif,
192};
193 168
194static int __init omap_dss_probe(struct platform_device *pdev) 169static int __init omap_dss_probe(struct platform_device *pdev)
195{ 170{
@@ -211,8 +186,6 @@ static int __init omap_dss_probe(struct platform_device *pdev)
211 else if (pdata->default_device) 186 else if (pdata->default_device)
212 core.default_display_name = pdata->default_device->name; 187 core.default_display_name = pdata->default_device->name;
213 188
214 register_pm_notifier(&omap_dss_pm_notif_block);
215
216 return 0; 189 return 0;
217 190
218err_debugfs: 191err_debugfs:
@@ -222,8 +195,6 @@ err_debugfs:
222 195
223static int omap_dss_remove(struct platform_device *pdev) 196static int omap_dss_remove(struct platform_device *pdev)
224{ 197{
225 unregister_pm_notifier(&omap_dss_pm_notif_block);
226
227 dss_uninitialize_debugfs(); 198 dss_uninitialize_debugfs();
228 199
229 return 0; 200 return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
index ef5b9027985d..24c2bffa0036 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -78,42 +78,6 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
78} 78}
79EXPORT_SYMBOL(omapdss_default_get_timings); 79EXPORT_SYMBOL(omapdss_default_get_timings);
80 80
81int dss_suspend_all_devices(void)
82{
83 struct omap_dss_device *dssdev = NULL;
84
85 for_each_dss_dev(dssdev) {
86 if (!dssdev->driver)
87 continue;
88
89 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
90 dssdev->driver->disable(dssdev);
91 dssdev->activate_after_resume = true;
92 } else {
93 dssdev->activate_after_resume = false;
94 }
95 }
96
97 return 0;
98}
99
100int dss_resume_all_devices(void)
101{
102 struct omap_dss_device *dssdev = NULL;
103
104 for_each_dss_dev(dssdev) {
105 if (!dssdev->driver)
106 continue;
107
108 if (dssdev->activate_after_resume) {
109 dssdev->driver->enable(dssdev);
110 dssdev->activate_after_resume = false;
111 }
112 }
113
114 return 0;
115}
116
117void dss_disable_all_devices(void) 81void dss_disable_all_devices(void)
118{ 82{
119 struct omap_dss_device *dssdev = NULL; 83 struct omap_dss_device *dssdev = NULL;
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h
index 9a6453235585..a974d46672db 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss.h
@@ -206,8 +206,6 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
206int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); 206int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
207 207
208/* display */ 208/* display */
209int dss_suspend_all_devices(void);
210int dss_resume_all_devices(void);
211void dss_disable_all_devices(void); 209void dss_disable_all_devices(void);
212 210
213int display_init_sysfs(struct platform_device *pdev); 211int display_init_sysfs(struct platform_device *pdev);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index dfafdb602ad2..e21433c3fda4 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -900,12 +900,52 @@ static int pdev_remove(struct platform_device *device)
900} 900}
901 901
902#ifdef CONFIG_PM_SLEEP 902#ifdef CONFIG_PM_SLEEP
903static int omap_drm_suspend_all_displays(void)
904{
905 struct omap_dss_device *dssdev = NULL;
906
907 for_each_dss_dev(dssdev) {
908 if (!dssdev->driver)
909 continue;
910
911 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
912 dssdev->driver->disable(dssdev);
913 dssdev->activate_after_resume = true;
914 } else {
915 dssdev->activate_after_resume = false;
916 }
917 }
918
919 return 0;
920}
921
922static int omap_drm_resume_all_displays(void)
923{
924 struct omap_dss_device *dssdev = NULL;
925
926 for_each_dss_dev(dssdev) {
927 if (!dssdev->driver)
928 continue;
929
930 if (dssdev->activate_after_resume) {
931 dssdev->driver->enable(dssdev);
932 dssdev->activate_after_resume = false;
933 }
934 }
935
936 return 0;
937}
938
903static int omap_drm_suspend(struct device *dev) 939static int omap_drm_suspend(struct device *dev)
904{ 940{
905 struct drm_device *drm_dev = dev_get_drvdata(dev); 941 struct drm_device *drm_dev = dev_get_drvdata(dev);
906 942
907 drm_kms_helper_poll_disable(drm_dev); 943 drm_kms_helper_poll_disable(drm_dev);
908 944
945 drm_modeset_lock_all(drm_dev);
946 omap_drm_suspend_all_displays();
947 drm_modeset_unlock_all(drm_dev);
948
909 return 0; 949 return 0;
910} 950}
911 951
@@ -913,6 +953,10 @@ static int omap_drm_resume(struct device *dev)
913{ 953{
914 struct drm_device *drm_dev = dev_get_drvdata(dev); 954 struct drm_device *drm_dev = dev_get_drvdata(dev);
915 955
956 drm_modeset_lock_all(drm_dev);
957 omap_drm_resume_all_displays();
958 drm_modeset_unlock_all(drm_dev);
959
916 drm_kms_helper_poll_enable(drm_dev); 960 drm_kms_helper_poll_enable(drm_dev);
917 961
918 return omap_gem_resume(dev); 962 return omap_gem_resume(dev);