summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorScott Peterson <speterson@nvidia.com>2012-12-27 19:11:42 -0800
committerSimone Willett <swillett@nvidia.com>2013-01-03 15:15:47 -0800
commit501983d17947d25a18ac527d020563b959942528 (patch)
tree1f015545b0eaf30d22422ed3813adb33acd89d33 /sound
parent2be11457a857263ee83263484af6294542230076 (diff)
asoc: tegra: Roth headphone detection
Fixed clocking issues when doing headphone detection on roth. The NXP device requires an active I2S interface in order to supply clocks for programming. Bug 1210696 Change-Id: I6e18daa349448d14e7ea2c98df2917213d24d82a Signed-off-by: Scott Peterson <speterson@nvidia.com> (cherry picked from commit 5d386c3275f38c84686f9b7f2181b5ecb08e0391) Reviewed-on: http://git-master/r/188063 Tested-by: Vinod Subbarayalu <vsubbarayalu@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_rt5640.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 3e606415aaec..d1280d3d4427 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -81,32 +81,8 @@ struct tegra_rt5640 {
volatile int clock_enabled;
};
-void enable_clks(struct tegra30_i2s *i2s)
-{
- tegra30_ahub_enable_clocks();
- clk_enable(i2s->clk_i2s);
- tegra30_ahub_enable_tx_fifo(i2s->txcif);
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
- #ifdef CONFIG_PM
- i2s->reg_cache[TEGRA30_I2S_CTRL >> 2] = i2s->reg_ctrl;
- #endif
- __raw_writel(i2s->reg_ctrl, i2s->regs + TEGRA30_I2S_CTRL);
-}
-
-void disable_clks(struct tegra30_i2s *i2s)
-{
- int dcnt = 10;
- i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
- #ifdef CONFIG_PM
- i2s->reg_cache[TEGRA30_I2S_CTRL >> 2] = i2s->reg_ctrl;
- #endif
- __raw_writel(i2s->reg_ctrl, i2s->regs + TEGRA30_I2S_CTRL);
- while (tegra30_ahub_tx_fifo_is_enabled(i2s->id) && dcnt--)
- udelay(100);
- clk_disable(i2s->clk_i2s);
- tegra30_ahub_disable_clocks();
- tegra30_ahub_disable_tx_fifo(i2s->txcif);
-}
+void tegra_asoc_enable_clocks(void);
+void tegra_asoc_disable_clocks(void);
static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -185,10 +161,10 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
if(machine_is_roth()) {
if(initTfa == 1) {
i2s_tfa = i2s;
- enable_clks(i2s);
+ tegra_asoc_enable_clocks();
pr_info("INIT TFA\n");
Tfa9887_Init(srate);
- disable_clks(i2s);
+ tegra_asoc_disable_clocks();
}
initTfa++;
}
@@ -461,9 +437,9 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
if(machine_is_roth()) {
if (SND_SOC_DAPM_EVENT_ON(event)) {
if(i2s_tfa) {
- enable_clks(i2s_tfa);
+ tegra_asoc_enable_clocks();
Tfa9887_Powerdown(0);
- disable_clks(i2s_tfa);
+ tegra_asoc_disable_clocks();
}
}
else {
@@ -474,7 +450,7 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
return 0;
gpio_set_value_cansleep(pdata->gpio_spkr_en,
- SND_SOC_DAPM_EVENT_ON(event));
+ !!SND_SOC_DAPM_EVENT_ON(event));
return 0;
}
@@ -515,7 +491,7 @@ static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
return 0;
gpio_set_value_cansleep(pdata->gpio_int_mic_en,
- SND_SOC_DAPM_EVENT_ON(event));
+ !!SND_SOC_DAPM_EVENT_ON(event));
return 0;
}
@@ -748,6 +724,49 @@ static struct snd_soc_card snd_soc_tegra_rt5640 = {
.fully_routed = true,
};
+void tegra_asoc_enable_clocks()
+{
+ struct snd_soc_card *card = &snd_soc_tegra_rt5640;
+ struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
+ int reg;
+ struct tegra30_i2s *i2s = i2s_tfa;
+ if (!i2s || !machine)
+ return;
+
+ reg = i2s->reg_ctrl | TEGRA30_I2S_CTRL_XFER_EN_TX;
+ if (!(i2s->reg_ctrl & TEGRA30_I2S_CTRL_XFER_EN_TX)) {
+ tegra_asoc_utils_clk_enable(&machine->util_data);
+ clk_enable(i2s->clk_i2s);
+ tegra30_ahub_enable_clocks();
+ tegra30_ahub_enable_tx_fifo(i2s->txcif);
+ __raw_writel(reg, i2s->regs + TEGRA30_I2S_CTRL);
+ }
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_enable_clocks);
+
+void tegra_asoc_disable_clocks()
+{
+ struct snd_soc_card *card = &snd_soc_tegra_rt5640;
+ struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
+ int dcnt = 10;
+ struct tegra30_i2s *i2s = i2s_tfa;
+ if (!i2s || !machine)
+ return;
+
+ if (!(i2s->reg_ctrl & TEGRA30_I2S_CTRL_XFER_EN_TX)) {
+ __raw_writel(i2s->reg_ctrl, i2s->regs + TEGRA30_I2S_CTRL);
+ while (!tegra30_ahub_tx_fifo_is_empty(i2s->id) && dcnt--)
+ udelay(100);
+
+ tegra30_ahub_disable_tx_fifo(i2s->txcif);
+ tegra30_ahub_disable_clocks();
+ clk_disable(i2s->clk_i2s);
+ tegra_asoc_utils_clk_disable(&machine->util_data);
+ }
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_disable_clocks);
+
+
static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_rt5640;