diff options
author | ScottPeterson <speterson@nvidia.com> | 2012-01-17 17:32:11 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-01-30 13:28:18 -0800 |
commit | 2e3c724c167ec5da8b1ed5ab07cda55232ecdf13 (patch) | |
tree | d82c4c6da45dd46de1aa0c75393869470fe033e3 /sound/soc/tegra/tegra_asoc_utils.c | |
parent | 6814bf677b18c10cee192e813d3d468b01229a25 (diff) |
asoc:tegra: Support I2S slave mode
Support I2S slave mode. Disable pll_p_out1 and
pll_a to reduce power when in slave mode.
Slave mode disabled by default.
Reviewed-on: http://git-master/r/76046
Change-Id: I873a11d54f1e037d99c86ff4cec06ee83064902a
Signed-off-by: ScottPeterson <speterson@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/77765
Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'sound/soc/tegra/tegra_asoc_utils.c')
-rw-r--r-- | sound/soc/tegra/tegra_asoc_utils.c | 107 |
1 files changed, 57 insertions, 50 deletions
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index c517bd04e2da..1f336d82bfe3 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -25,6 +25,8 @@ #include <linux/err.h> #include <linux/kernel.h> +#include <mach/clk.h> + #include "tegra_asoc_utils.h" int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, @@ -33,6 +35,7 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, int new_baseclock; bool clk_change; int err; + bool reenable_clock; switch (srate) { case 11025: @@ -73,41 +76,32 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, data->set_baseclock = 0; data->set_mclk = 0; - clk_disable(data->clk_cdev1); - clk_disable(data->clk_pll_a_out0); - clk_disable(data->clk_pll_a); - + reenable_clock = false; + if(tegra_is_clk_enabled(data->clk_pll_a)) { + clk_disable(data->clk_pll_a); + reenable_clock = true; + } err = clk_set_rate(data->clk_pll_a, new_baseclock); if (err) { dev_err(data->dev, "Can't set pll_a rate: %d\n", err); return err; } + if(reenable_clock) + clk_enable(data->clk_pll_a); - err = clk_set_rate(data->clk_pll_a_out0, mclk); - if (err) { - dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); - return err; + reenable_clock = false; + if(tegra_is_clk_enabled(data->clk_pll_a_out0)) { + clk_disable(data->clk_pll_a_out0); + reenable_clock = true; } - - /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ - - err = clk_enable(data->clk_pll_a); - if (err) { - dev_err(data->dev, "Can't enable pll_a: %d\n", err); - return err; - } - - err = clk_enable(data->clk_pll_a_out0); + err = clk_set_rate(data->clk_pll_a_out0, mclk); if (err) { - dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); + dev_err(data->dev, "Can't set clk_pll_a_out0 rate: %d\n", err); return err; } + if(reenable_clock) + clk_enable(data->clk_pll_a_out0); - err = clk_enable(data->clk_cdev1); - if (err) { - dev_err(data->dev, "Can't enable cdev1: %d\n", err); - return err; - } data->set_baseclock = new_baseclock; data->set_mclk = mclk; @@ -130,18 +124,6 @@ int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data) { int err; - err = clk_enable(data->clk_pll_a); - if (err) { - dev_err(data->dev, "Can't enable pll_a: %d\n", err); - return err; - } - - err = clk_enable(data->clk_pll_a_out0); - if (err) { - dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); - return err; - } - err = clk_enable(data->clk_cdev1); if (err) { dev_err(data->dev, "Can't enable cdev1: %d\n", err); @@ -155,8 +137,6 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_enable); int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data) { clk_disable(data->clk_cdev1); - clk_disable(data->clk_pll_a_out0); - clk_disable(data->clk_pll_a); return 0; } EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable); @@ -165,14 +145,22 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, struct device *dev) { int ret; + int rate; data->dev = dev; + data->clk_pll_p_out1 = clk_get_sys(NULL, "pll_p_out1"); + if (IS_ERR(data->clk_pll_p_out1)) { + dev_err(data->dev, "Can't retrieve clk pll_p_out1\n"); + ret = PTR_ERR(data->clk_pll_p_out1); + goto err; + } + data->clk_pll_a = clk_get_sys(NULL, "pll_a"); if (IS_ERR(data->clk_pll_a)) { dev_err(data->dev, "Can't retrieve clk pll_a\n"); ret = PTR_ERR(data->clk_pll_a); - goto err; + goto err_put_pll_p_out1; } data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); @@ -182,6 +170,13 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, goto err_put_pll_a; } + data->clk_m = clk_get_sys(NULL, "clk_m"); + if (IS_ERR(data->clk_m)) { + dev_err(data->dev, "Can't retrieve clk clk_m\n"); + ret = PTR_ERR(data->clk_m); + goto err; + } + #if defined(CONFIG_ARCH_TEGRA_2x_SOC) data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); #else @@ -204,26 +199,28 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, } #endif - ret = clk_enable(data->clk_pll_a); +#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) +#if TEGRA30_I2S_MASTER_PLAYBACK + ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0); if (ret) { - dev_err(data->dev, "Can't enable clk pll_a"); + dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); goto err_put_out1; } +#else + rate = clk_get_rate(data->clk_m); - ret = clk_enable(data->clk_pll_a_out0); - if (ret) { - dev_err(data->dev, "Can't enable clk pll_a_out0"); - goto err_put_out1; - } + if(rate == 26000000) + clk_set_rate(data->clk_cdev1, 13000000); -#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) - ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0); + ret = clk_set_parent(data->clk_cdev1, data->clk_m); if (ret) { dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); goto err_put_out1; } #endif +#endif + ret = clk_enable(data->clk_cdev1); if (ret) { dev_err(data->dev, "Can't enable clk cdev1/extern1"); @@ -255,6 +252,8 @@ err_put_pll_a_out0: clk_put(data->clk_pll_a_out0); err_put_pll_a: clk_put(data->clk_pll_a); +err_put_pll_p_out1: + clk_put(data->clk_pll_p_out1); err: return ret; } @@ -264,9 +263,17 @@ void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) { if (!IS_ERR(data->clk_out1)) clk_put(data->clk_out1); + clk_put(data->clk_cdev1); - clk_put(data->clk_pll_a_out0); - clk_put(data->clk_pll_a); + + if (!IS_ERR(data->clk_pll_a_out0)) + clk_put(data->clk_pll_a_out0); + + if (!IS_ERR(data->clk_pll_a)) + clk_put(data->clk_pll_a); + + if (!IS_ERR(data->clk_pll_p_out1)) + clk_put(data->clk_pll_p_out1); } EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini); |