diff options
author | Stephen Warren <swarren@nvidia.com> | 2011-06-30 15:05:47 -0600 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2011-08-04 22:57:53 -0600 |
commit | 2e39114fff798e8904f4c51877ff426799bf0101 (patch) | |
tree | 6c776a8387e7b96399b7f7314e10fcf25d7409ad /sound | |
parent | fd5d53246d4b4858b95f41f5b40d973b665c6fad (diff) |
ASoC: Tegra: I2S: Modify clock management logic
Modify the clock management logic to match that implemented in the
upcoming Tegra30 ASoC driver.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/tegra/tegra_i2s.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 2e5685512db0..e178b46af28d 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c @@ -57,6 +57,22 @@ static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg) return __raw_readl(i2s->regs + reg); } +static void tegra_i2s_inc_clock_ref(struct tegra_i2s *i2s) +{ + i2s->clk_refs++; + if (i2s->clk_refs == 1) + clk_enable(i2s->clk_i2s); +} + +static void tegra_i2s_dec_clock_ref(struct tegra_i2s *i2s) +{ + BUG_ON(!i2s->clk_refs); + + i2s->clk_refs--; + if (!i2s->clk_refs) + clk_enable(i2s->clk_i2s); +} + #ifdef CONFIG_DEBUG_FS static int tegra_i2s_show(struct seq_file *s, void *unused) { @@ -79,11 +95,15 @@ static int tegra_i2s_show(struct seq_file *s, void *unused) struct tegra_i2s *i2s = s->private; int i; + tegra_i2s_inc_clock_ref(i2s); + for (i = 0; i < ARRAY_SIZE(regs); i++) { u32 val = tegra_i2s_read(i2s, regs[i].offset); seq_printf(s, "%s = %08x\n", regs[i].name, val); } + tegra_i2s_dec_clock_ref(i2s); + return 0; } @@ -222,12 +242,16 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, if (i2sclock % (2 * srate)) reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; + tegra_i2s_inc_clock_ref(i2s); + tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); + tegra_i2s_dec_clock_ref(i2s); + return 0; } @@ -264,9 +288,7 @@ static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - if (!i2s->clk_refs) - clk_enable(i2s->clk_i2s); - i2s->clk_refs++; + tegra_i2s_inc_clock_ref(i2s); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) tegra_i2s_start_playback(i2s); else @@ -279,9 +301,7 @@ static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd, tegra_i2s_stop_playback(i2s); else tegra_i2s_stop_capture(i2s); - i2s->clk_refs--; - if (!i2s->clk_refs) - clk_disable(i2s->clk_i2s); + tegra_i2s_dec_clock_ref(i2s); break; default: return -EINVAL; |