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 <jonathanh@nvidia.com>
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 <bbasu@nvidia.com>
This commit is contained in:
Jon Hunter
2017-05-24 17:35:15 +01:00
committed by Sameer Pujar
parent a29581fc2e
commit f8c3f7a29e
3 changed files with 42 additions and 6 deletions

View File

@@ -106,7 +106,18 @@ static int tegra186_arad_runtime_resume(struct device *dev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int tegra186_arad_suspend(struct device *dev) static int tegra186_arad_suspend(struct device *dev)
{ {
if (pm_runtime_status_suspended(dev))
return 0; 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 #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 = { static const struct dev_pm_ops tegra186_arad_pm_ops = {
SET_RUNTIME_PM_OPS(tegra186_arad_runtime_suspend, SET_RUNTIME_PM_OPS(tegra186_arad_runtime_suspend,
tegra186_arad_runtime_resume, NULL) 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 = { static struct platform_driver tegra186_arad_driver = {

View File

@@ -229,7 +229,18 @@ static int tegra186_asrc_runtime_resume(struct device *dev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int tegra186_asrc_suspend(struct device *dev) static int tegra186_asrc_suspend(struct device *dev)
{ {
if (pm_runtime_status_suspended(dev))
return 0; 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 #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 = { static const struct dev_pm_ops tegra186_asrc_pm_ops = {
SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend, SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
tegra186_asrc_runtime_resume, NULL) 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 = { static struct platform_driver tegra186_asrc_driver = {

View File

@@ -141,7 +141,18 @@ static int tegra186_dspk_runtime_resume(struct device *dev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int tegra186_dspk_suspend(struct device *dev) static int tegra186_dspk_suspend(struct device *dev)
{ {
if (pm_runtime_status_suspended(dev))
return 0; 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 #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 = { static const struct dev_pm_ops tegra186_dspk_pm_ops = {
SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend,
tegra186_dspk_runtime_resume, NULL) 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 = { static struct platform_driver tegra186_dspk_driver = {