diff options
author | Shawn Guo <shawn.guo@freescale.com> | 2014-09-10 22:43:51 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-23 23:36:27 -0700 |
commit | bfe945c8e1260e405a7a257719c9e2cf77cafa4e (patch) | |
tree | e074e1dcf745b9a1967a02df7efd05a5d273f488 /drivers/staging/imx-drm | |
parent | b46355f0f77f6553ad6079ffd6ee5adfb8ca7a8b (diff) |
imx-drm: imx-drm-core: add basic suspend/resume support
HDMI currently stops working after a system suspend/resume cycle. The
cause is that the mode setting states in hardware gets lost and isn't
restored across the suspend/resume cycle.
The patch adds a very basic suspend/resume support to imx-drm driver,
and calls drm_helper_resume_force_mode() in .resume hook to restore the
mode setting states, so that HDMI can continue working after a system
suspend/resume cycle.
Since the suspend/resume hook can be called with drm_device pointer
being NULL from driver data, we need a check on the pointer in the
hooks. And to avoid using a stale pointer from driver data, it also
clears driver data in .unload hook.
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/imx-drm')
-rw-r--r-- | drivers/staging/imx-drm/imx-drm-core.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 4289cc8963e4..b18847827759 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -87,6 +87,8 @@ static int imx_drm_driver_unload(struct drm_device *drm) drm_vblank_cleanup(drm); drm_mode_config_cleanup(drm); + platform_set_drvdata(drm->platformdev, NULL); + return 0; } @@ -648,6 +650,36 @@ static int imx_drm_platform_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int imx_drm_suspend(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + /* The drm_dev is NULL before .load hook is called */ + if (drm_dev == NULL) + return 0; + + drm_kms_helper_poll_disable(drm_dev); + + return 0; +} + +static int imx_drm_resume(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + if (drm_dev == NULL) + return 0; + + drm_helper_resume_force_mode(drm_dev); + drm_kms_helper_poll_enable(drm_dev); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume); + static const struct of_device_id imx_drm_dt_ids[] = { { .compatible = "fsl,imx-display-subsystem", }, { /* sentinel */ }, @@ -660,6 +692,7 @@ static struct platform_driver imx_drm_pdrv = { .driver = { .owner = THIS_MODULE, .name = "imx-drm", + .pm = &imx_drm_pm_ops, .of_match_table = imx_drm_dt_ids, }, }; |