diff options
author | Stephen Warren <swarren@nvidia.com> | 2011-06-30 15:05:47 -0600 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:43:19 -0800 |
commit | 79911866d84738242f547120ebe4eac3d42bf69d (patch) | |
tree | f8606c9be50a7246da3f73a781a14aba63250863 /sound | |
parent | fb890857b61489bd2cf0ad03a6ef6e7de95f5df1 (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>
Rebase-Id: R2e5a6c0989f3f91c95cf4e6ad890fc236bcd8fa5
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/tegra/tegra_i2s.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index f36b9969cfec..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,8 +242,7 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, if (i2sclock % (2 * srate)) reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; - if (!i2s->clk_refs) - clk_enable(i2s->clk_i2s); + tegra_i2s_inc_clock_ref(i2s); tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); @@ -231,8 +250,7 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); - if (!i2s->clk_refs) - clk_disable(i2s->clk_i2s); + tegra_i2s_dec_clock_ref(i2s); return 0; } @@ -270,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 @@ -285,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; |