From f8c3f7a29e42e28aeaa512ca0bf93da0c92ecb89 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 24 May 2017 17:35:15 +0100 Subject: [PATCH] ASoC: tegra-alt: Fix system suspend handling There are a couple issues with system suspend handling in the Tegra ASoC codec drivers which are: 1. Most drivers the system suspend callback does nothing and this means that if the codec device is active when suspend occurs then the codec will not be suspended correctly. This has been seen to cause system crashes in the I2S driver when the system is suspended and resuming while audio playback is active. 2. The codec suspend handlers may be called twice when entering suspend. Suspend handlers should only be called once, but currently they are called twice; once by the PM core and once when the APE power-domain is turned off (if it is on when suspend occurs). Fix the above two problems by: a). Adding proper system suspend and resume handlers for all codec drivers, to suspend and resume the device if not runtime PM suspended on entering suspend. b). Remove the code to call the PM callbacks from the APE power-domain code. Finally, make the system suspend callbacks for these codec drivers late suspend callbacks to ensure that the sound core has suspended any on-going activity, before we attempt to suspend these codec devices. Bug 200275736 Change-Id: I7f43b8650d972356b0a529404792fe22125dde16 Signed-off-by: Jon Hunter Reviewed-on: http://git-master/r/1488962 (cherry picked from commit 5a7f3ab3d1e6d9d136859b9263b91e3f6998366b) Reviewed-on: https://git-master/r/1511033 GVS: Gerrit_Virtual_Submit Reviewed-by: Bibek Basu --- sound/soc/tegra-alt/tegra186_arad_alt.c | 16 ++++++++++++++-- sound/soc/tegra-alt/tegra186_asrc_alt.c | 16 ++++++++++++++-- sound/soc/tegra-alt/tegra186_dspk_alt.c | 16 ++++++++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/sound/soc/tegra-alt/tegra186_arad_alt.c b/sound/soc/tegra-alt/tegra186_arad_alt.c index 5a9ca9e7..9f918d80 100644 --- a/sound/soc/tegra-alt/tegra186_arad_alt.c +++ b/sound/soc/tegra-alt/tegra186_arad_alt.c @@ -106,7 +106,18 @@ static int tegra186_arad_runtime_resume(struct device *dev) #ifdef CONFIG_PM_SLEEP static int tegra186_arad_suspend(struct device *dev) { - return 0; + if (pm_runtime_status_suspended(dev)) + return 0; + + return tegra186_arad_runtime_suspend(dev); +} + +static int tegra186_arad_resume(struct device *dev) +{ + if (pm_runtime_status_suspended(dev)) + return 0; + + return tegra186_arad_runtime_resume(dev); } #endif @@ -894,7 +905,8 @@ static int tegra186_arad_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra186_arad_pm_ops = { SET_RUNTIME_PM_OPS(tegra186_arad_runtime_suspend, tegra186_arad_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(tegra186_arad_suspend, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(tegra186_arad_suspend, + tegra186_arad_resume) }; static struct platform_driver tegra186_arad_driver = { diff --git a/sound/soc/tegra-alt/tegra186_asrc_alt.c b/sound/soc/tegra-alt/tegra186_asrc_alt.c index dad8016f..136f1cd0 100644 --- a/sound/soc/tegra-alt/tegra186_asrc_alt.c +++ b/sound/soc/tegra-alt/tegra186_asrc_alt.c @@ -229,7 +229,18 @@ static int tegra186_asrc_runtime_resume(struct device *dev) #ifdef CONFIG_PM_SLEEP static int tegra186_asrc_suspend(struct device *dev) { - return 0; + if (pm_runtime_status_suspended(dev)) + return 0; + + return tegra186_asrc_runtime_suspend(dev); +} + +static int tegra186_asrc_resume(struct device *dev) +{ + if (pm_runtime_status_suspended(dev)) + return 0; + + return tegra186_asrc_runtime_resume(dev); } #endif @@ -1252,7 +1263,8 @@ static int tegra186_asrc_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra186_asrc_pm_ops = { SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend, tegra186_asrc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(tegra186_asrc_suspend, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(tegra186_asrc_suspend, + tegra186_asrc_resume) }; static struct platform_driver tegra186_asrc_driver = { diff --git a/sound/soc/tegra-alt/tegra186_dspk_alt.c b/sound/soc/tegra-alt/tegra186_dspk_alt.c index 7a074cc0..c02a4651 100644 --- a/sound/soc/tegra-alt/tegra186_dspk_alt.c +++ b/sound/soc/tegra-alt/tegra186_dspk_alt.c @@ -141,7 +141,18 @@ static int tegra186_dspk_runtime_resume(struct device *dev) #ifdef CONFIG_PM_SLEEP static int tegra186_dspk_suspend(struct device *dev) { - return 0; + if (pm_runtime_status_suspended(dev)) + return 0; + + return tegra186_dspk_runtime_suspend(dev); +} + +static int tegra186_dspk_resume(struct device *dev) +{ + if (pm_runtime_status_suspended(dev)) + return 0; + + return tegra186_dspk_runtime_resume(dev); } #endif @@ -625,7 +636,8 @@ static int tegra186_dspk_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra186_dspk_pm_ops = { SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, tegra186_dspk_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(tegra186_dspk_suspend, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(tegra186_dspk_suspend, + tegra186_dspk_resume) }; static struct platform_driver tegra186_dspk_driver = {