From 8bd1b0a7aeadc83a0564c84aa01e91c151da062e Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Fri, 10 Oct 2014 16:46:22 +0530 Subject: [PATCH] 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 Reviewed-on: http://git-master/r/555433 --- sound/soc/tegra-alt/tegra210_adsp_alt.c | 23 ++++++++++++++++++++--- sound/soc/tegra-alt/tegra210_xbar_alt.c | 15 +++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra-alt/tegra210_adsp_alt.c b/sound/soc/tegra-alt/tegra210_adsp_alt.c index ee7f5fdb..a4936b7e 100644 --- a/sound/soc/tegra-alt/tegra210_adsp_alt.c +++ b/sound/soc/tegra-alt/tegra210_adsp_alt.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -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; } diff --git a/sound/soc/tegra-alt/tegra210_xbar_alt.c b/sound/soc/tegra-alt/tegra210_xbar_alt.c index 6f983d98..62e2d191 100644 --- a/sound/soc/tegra-alt/tegra210_xbar_alt.c +++ b/sound/soc/tegra-alt/tegra210_xbar_alt.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -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);