summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-06-30 15:05:47 -0600
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:43:19 -0800
commit79911866d84738242f547120ebe4eac3d42bf69d (patch)
treef8606c9be50a7246da3f73a781a14aba63250863 /sound
parentfb890857b61489bd2cf0ad03a6ef6e7de95f5df1 (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.c34
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;