summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-06-30 15:05:47 -0600
committerStephen Warren <swarren@nvidia.com>2011-08-04 22:57:53 -0600
commit2e39114fff798e8904f4c51877ff426799bf0101 (patch)
tree6c776a8387e7b96399b7f7314e10fcf25d7409ad /sound
parentfd5d53246d4b4858b95f41f5b40d973b665c6fad (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.c32
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;