ASoC: tegra-alt: Add APE power domain support

1. Add APE power domain support to xbar and adsp driver.
2. Also add runtime PM support in adsp audio driver to ensure APE PM
   domain works properly.
3. Add code in xbar system suspend callback to support calling of all
   xbar child driver system suspend. This is required to properly
   support APE PM domain.

Bug 200039212

Change-Id: Ieb937b05e39d4e980872745e3b6580bca3eb6956
Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-on: http://git-master/r/555433
This commit is contained in:
Sumit Bhattacharya
2014-10-10 16:46:22 +05:30
committed by Sameer Pujar
parent dbae79bb60
commit 8bd1b0a7ae
2 changed files with 35 additions and 3 deletions

View File

@@ -30,6 +30,8 @@
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/tegra_pm_domains.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
@@ -1909,6 +1911,7 @@ static int tegra210_adsp_codec_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver tegra210_adsp_codec = {
.probe = tegra210_adsp_codec_probe,
.idle_bias_off = 1,
};
static struct snd_soc_platform_driver tegra210_adsp_platform = {
@@ -1947,6 +1950,15 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
pdev->dev.dma_mask = &tegra_dma_mask;
pdev->dev.coherent_dma_mask = tegra_dma_mask;
tegra_ape_pd_add_device(&pdev->dev);
pm_genpd_dev_need_save(&pdev->dev, true);
pm_genpd_dev_need_restore(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev))
goto err_pm_disable;
pm_runtime_get_sync(&pdev->dev);
/* HACK : Should be handled through dma-engine */
for (i = 0; i < TEGRA210_ADSP_ADMA_CHANNEL_COUNT; i++) {
ret = tegra_agic_route_interrupt(
@@ -1954,10 +1966,11 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
TEGRA_AGIC_ADSP);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to route INT to ADSP");
return ret;
goto err_pm_disable;
}
}
/* HACK end */
pm_runtime_put(&pdev->dev);
for (i = 0; i < TEGRA210_ADSP_VIRT_REG_MAX; i++)
adsp->apps[i].reg = i;
@@ -1971,7 +1984,7 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
ret = snd_soc_register_platform(&pdev->dev, &tegra210_adsp_platform);
if (ret) {
dev_err(&pdev->dev, "Could not register platform: %d\n", ret);
goto err;
goto err_pm_disable;
}
ret = snd_soc_register_component(&pdev->dev, &tegra210_adsp_component,
@@ -1994,12 +2007,16 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
err_unregister_platform:
snd_soc_unregister_platform(&pdev->dev);
err:
err_pm_disable:
pm_runtime_disable(&pdev->dev);
tegra_ape_pd_remove_device(&pdev->dev);
return ret;
}
static int tegra210_adsp_audio_platform_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
tegra_ape_pd_remove_device(&pdev->dev);
snd_soc_unregister_platform(&pdev->dev);
return 0;
}

View File

@@ -23,6 +23,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/tegra_pm_domains.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/soc.h>
@@ -82,9 +83,16 @@ static int tegra210_xbar_runtime_resume(struct device *dev)
}
#ifdef CONFIG_PM_SLEEP
static int tegra210_xbar_child_suspend(struct device *dev, void *data)
{
return platform_pm_suspend(dev);
}
static int tegra210_xbar_suspend(struct device *dev)
{
regcache_mark_dirty(xbar->regmap);
device_for_each_child(dev, NULL, tegra210_xbar_child_suspend);
return 0;
}
#endif
@@ -904,6 +912,10 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
}
regcache_cache_only(xbar->regmap, true);
tegra_ape_pd_add_device(&pdev->dev);
pm_genpd_dev_need_save(&pdev->dev, true);
pm_genpd_dev_need_restore(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = tegra210_xbar_runtime_resume(&pdev->dev);
@@ -927,6 +939,7 @@ err_suspend:
tegra210_xbar_runtime_suspend(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
tegra_ape_pd_remove_device(&pdev->dev);
err_clk_set_parent:
clk_set_parent(xbar->clk, parent_clk);
err_clk_put_ape:
@@ -947,6 +960,8 @@ static int tegra210_xbar_remove(struct platform_device *pdev)
if (!pm_runtime_status_suspended(&pdev->dev))
tegra210_xbar_runtime_suspend(&pdev->dev);
tegra_ape_pd_remove_device(&pdev->dev);
devm_clk_put(&pdev->dev, xbar->clk);
clk_put(xbar->clk_parent);
clk_put(xbar->clk_ape);