mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
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:
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user