aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-06-26 08:52:16 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-06-29 02:09:40 -0400
commit2b8501d777346ce1d4fe99167e9b3c0e42aae7a8 (patch)
tree9f731e7f8fcfd80e9a0f47c6b2dd68c9016cdbcc /drivers/video
parentf11766d1c210aca50e772f55457fea113d8f511a (diff)
OMAPDSS: Use PM notifiers for system suspend
The current way how omapdss handles system suspend and resume is that omapdss device (a platform device, which is not part of the device hierarchy of the DSS HW devices, like DISPC and DSI, or panels.) uses the suspend and resume callbacks from platform_driver to handle system suspend. It does this by disabling all enabled panels on suspend, and resuming the previously disabled panels on resume. This presents a few problems. One is that as omapdss device is not related to the panel devices or the DSS HW devices, there's no ordering in the suspend process. This means that suspend could be first ran for DSS HW devices and panels, and only then for omapdss device. Currently this is not a problem, as DSS HW devices and panels do not handle suspend. Another, more pressing problem, is that when suspending or resuming, the runtime PM functions return -EACCES as runtime PM is disabled during system suspend. This causes the driver to print warnings, and operations to fail as they think that they failed to bring up the HW. This patch changes the omapdss suspend handling to use PM notifiers, which are called before suspend and after resume. This way we have a normally functioning system when we are suspending and resuming the panels. This patch, I believe, creates a problem that somebody could enable or disable a panel between PM_SUSPEND_PREPARE and the system suspend, and similarly the other way around in resume. I choose to ignore the problem for now, as it sounds rather unlikely, and if it happens, it's not fatal. In the long run the system suspend handling of omapdss and panels should be thought out properly. The current approach feels rather hacky. Perhaps the panel drivers should handle system suspend, or the users of omapdss (omapfb, omapdrm) should handle system suspend. Note that after this patch we could probably revert 0eaf9f52e94f756147dbfe1faf1f77a02378dbf9 (OMAPDSS: use sync versions of pm_runtime_put). But as I said, this patch may be temporary, so let's leave the sync version still in place. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Reported-by: Jassi Brar <jaswinder.singh@linaro.org> Tested-by: Jassi Brar <jaswinder.singh@linaro.org>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/core.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 5066eee10ccf..c35a248c5e35 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -32,6 +32,7 @@
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/suspend.h>
35 36
36#include <video/omapdss.h> 37#include <video/omapdss.h>
37 38
@@ -201,6 +202,30 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
201#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 202#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
202 203
203/* PLATFORM DEVICE */ 204/* PLATFORM DEVICE */
205static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
206{
207 DSSDBG("pm notif %lu\n", v);
208
209 switch (v)
210 {
211 case PM_SUSPEND_PREPARE:
212 DSSDBG("suspending displays\n");
213 return dss_suspend_all_devices();
214
215 case PM_POST_SUSPEND:
216 DSSDBG("resuming displays\n");
217 return dss_resume_all_devices();
218
219 default:
220 return 0;
221 }
222}
223
224static struct notifier_block omap_dss_pm_notif_block =
225{
226 .notifier_call = omap_dss_pm_notif,
227};
228
204static int __init omap_dss_probe(struct platform_device *pdev) 229static int __init omap_dss_probe(struct platform_device *pdev)
205{ 230{
206 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 231 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
@@ -224,6 +249,8 @@ static int __init omap_dss_probe(struct platform_device *pdev)
224 else if (pdata->default_device) 249 else if (pdata->default_device)
225 core.default_display_name = pdata->default_device->name; 250 core.default_display_name = pdata->default_device->name;
226 251
252 register_pm_notifier(&omap_dss_pm_notif_block);
253
227 return 0; 254 return 0;
228 255
229err_debugfs: 256err_debugfs:
@@ -233,6 +260,8 @@ err_debugfs:
233 260
234static int omap_dss_remove(struct platform_device *pdev) 261static int omap_dss_remove(struct platform_device *pdev)
235{ 262{
263 unregister_pm_notifier(&omap_dss_pm_notif_block);
264
236 dss_uninitialize_debugfs(); 265 dss_uninitialize_debugfs();
237 266
238 dss_uninit_overlays(pdev); 267 dss_uninit_overlays(pdev);
@@ -247,25 +276,9 @@ static void omap_dss_shutdown(struct platform_device *pdev)
247 dss_disable_all_devices(); 276 dss_disable_all_devices();
248} 277}
249 278
250static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
251{
252 DSSDBG("suspend %d\n", state.event);
253
254 return dss_suspend_all_devices();
255}
256
257static int omap_dss_resume(struct platform_device *pdev)
258{
259 DSSDBG("resume\n");
260
261 return dss_resume_all_devices();
262}
263
264static struct platform_driver omap_dss_driver = { 279static struct platform_driver omap_dss_driver = {
265 .remove = omap_dss_remove, 280 .remove = omap_dss_remove,
266 .shutdown = omap_dss_shutdown, 281 .shutdown = omap_dss_shutdown,
267 .suspend = omap_dss_suspend,
268 .resume = omap_dss_resume,
269 .driver = { 282 .driver = {
270 .name = "omapdss", 283 .name = "omapdss",
271 .owner = THIS_MODULE, 284 .owner = THIS_MODULE,