From c279bec375d672c91d38925e9ae3924b36d55dc7 Mon Sep 17 00:00:00 2001 From: Dipesh Gandhi Date: Wed, 18 May 2016 11:55:41 +0530 Subject: [PATCH] tegra-alt: adsp: clk to adsp_audio Currently adsp_audio rely on xbar device to keep clock enable. For some of corner cases it is observed that xbar devices gets to suspend state leading to disabling of ahub clock, however nvadma still trying to program adma. This leads to adsp crash. This change adds support for adsp_audio to enable and disable clocks as per its runtime_resume and runtime_suspend calls. Bug 1756112 Change-Id: I5697853d901eed1059bd1ce29099a74cf62d46a3 Signed-off-by: Dipesh Gandhi Reviewed-on: http://git-master/r/1149568 (cherry picked from commit 17d84bd026751e1bc380d69bd89c4a034d9398fc) Reviewed-on: http://git-master/r/1155917 (cherry picked from commit 0ef2ab54b1da6a9573c863ac8e60e7192ae3b2d6) Reviewed-on: http://git-master/r/1163157 GVS: Gerrit_Virtual_Submit Tested-by: Ravindra Lokhande Reviewed-by: Mohan Kumar D Reviewed-by: Sumit Bhattacharya --- sound/soc/tegra-alt/tegra210_adsp_alt.c | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/sound/soc/tegra-alt/tegra210_adsp_alt.c b/sound/soc/tegra-alt/tegra210_adsp_alt.c index 1d41dd5c..1223fcde 100644 --- a/sound/soc/tegra-alt/tegra210_adsp_alt.c +++ b/sound/soc/tegra-alt/tegra210_adsp_alt.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ #include #include "tegra_isomgr_bw_alt.h" +#include "tegra_asoc_utils_alt.h" #include "tegra210_adsp_alt.h" #define DRV_NAME "tegra210-adsp" @@ -124,6 +126,9 @@ struct tegra210_adsp { struct tegra210_adsp_app apps[TEGRA210_ADSP_VIRT_REG_MAX]; atomic_t reg_val[TEGRA210_ADSP_VIRT_REG_MAX]; DECLARE_BITMAP(adma_usage, TEGRA210_ADSP_ADMA_CHANNEL_COUNT); + struct clk *ahub_clk; + struct clk *ape_clk; + struct clk *apb2ape_clk; uint32_t i2s_rate; struct mutex mutex; int init_done; @@ -1889,6 +1894,13 @@ static int tegra210_adsp_runtime_suspend(struct device *dev) adsp->adsp_started = 0; + if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { + if (IS_ENABLED(CONFIG_ARCH_TEGRA_18x_SOC)) + clk_disable_unprepare(adsp->apb2ape_clk); + clk_disable_unprepare(adsp->ahub_clk); + clk_disable_unprepare(adsp->ape_clk); + } + return ret; } @@ -1901,7 +1913,28 @@ static int tegra210_adsp_runtime_resume(struct device *dev) if (!adsp->init_done) return 0; + if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { + ret = clk_prepare_enable(adsp->ahub_clk); + if (ret < 0) { + dev_err(dev, "ahub clk_enable failed: %d\n", ret); + return ret; + } + ret = clk_prepare_enable(adsp->ape_clk); + if (ret < 0) { + dev_err(dev, "ape clk_enable failed: %d\n", ret); + return ret; + } + + if (IS_ENABLED(CONFIG_ARCH_TEGRA_18x_SOC)) { + ret = clk_prepare_enable(adsp->apb2ape_clk); + if (ret < 0) { + dev_err(dev, "apb2ape clk_enable failed: %d\n" + , ret); + return ret; + } + } + } ret = nvadsp_os_start(); if (ret) { dev_err(adsp->dev, "Failed to start ADSP OS ret 0x%x", ret); @@ -3212,6 +3245,45 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, adsp); adsp->dev = &pdev->dev; + + if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { + if (IS_ENABLED(CONFIG_ARCH_TEGRA_21x_SOC)) { + adsp->ahub_clk = clk_get_sys("tegra210-adsp", "ahub"); + if (IS_ERR(adsp->ahub_clk)) { + dev_err(&pdev->dev, "Error: Missing AHUB clock\n"); + ret = PTR_ERR(adsp->ahub_clk); + goto err; + } + adsp->ape_clk = clk_get_sys(NULL, "adsp.ape"); + if (IS_ERR(adsp->ape_clk)) { + dev_err(&pdev->dev, "Error: Missing APE clock\n"); + ret = PTR_ERR(adsp->ape_clk); + goto err; + } + } else { + adsp->ahub_clk = devm_clk_get(&pdev->dev, "ahub"); + if (IS_ERR(adsp->ahub_clk)) { + dev_err(&pdev->dev, "Error: Missing AHUB clock\n"); + ret = PTR_ERR(adsp->ahub_clk); + goto err; + } + + adsp->ape_clk = devm_clk_get(&pdev->dev, "ape"); + if (IS_ERR(adsp->ape_clk)) { + dev_err(&pdev->dev, "Error: Missing APE clock\n"); + ret = PTR_ERR(adsp->ape_clk); + goto err; + } + + adsp->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape"); + if (IS_ERR(adsp->apb2ape_clk)) { + dev_err(&pdev->dev, "Error: Missing APB2APE clock\n"); + ret = PTR_ERR(adsp->apb2ape_clk); + goto err; + } + } + } + /* TODO: Add mixer control to set I2S playback rate */ adsp->i2s_rate = 48000; mutex_init(&adsp->mutex); @@ -3371,12 +3443,39 @@ err_unregister_platform: snd_soc_unregister_platform(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); +err: + if (IS_ENABLED(CONFIG_ARCH_TEGRA_18x_SOC)) + if (!IS_ERR_OR_NULL(adsp->apb2ape_clk)) + tegra_alt_asoc_utils_clk_put + (&pdev->dev, adsp->apb2ape_clk); + + if (!IS_ERR_OR_NULL(adsp->ape_clk)) + tegra_alt_asoc_utils_clk_put + (&pdev->dev, adsp->ape_clk); + if (!IS_ERR_OR_NULL(adsp->ahub_clk)) + tegra_alt_asoc_utils_clk_put + (&pdev->dev, adsp->ahub_clk); return ret; } static int tegra210_adsp_audio_platform_remove(struct platform_device *pdev) { + struct tegra210_adsp *adsp = dev_get_drvdata(&pdev->dev); + pm_runtime_disable(&pdev->dev); + if (IS_ENABLED(CONFIG_ARCH_TEGRA_18x_SOC)) + if (!IS_ERR_OR_NULL(adsp->apb2ape_clk)) + tegra_alt_asoc_utils_clk_put + (&pdev->dev, adsp->apb2ape_clk); + + if (!IS_ERR_OR_NULL(adsp->ape_clk)) + tegra_alt_asoc_utils_clk_put + (&pdev->dev, adsp->ape_clk); + + if (!IS_ERR_OR_NULL(adsp->ahub_clk)) + tegra_alt_asoc_utils_clk_put + (&pdev->dev, adsp->ahub_clk); + tegra_pd_remove_device(&pdev->dev); snd_soc_unregister_platform(&pdev->dev); return 0;