aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2009-11-07 03:34:43 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-11-07 07:40:09 -0500
commitc939e5c82142978d9d534aca34187a8489fd13f3 (patch)
tree5c0ea0815d98c71371feb25f76e852f2123e0d95
parent1d8222e8df07ce4f86fb7fa80b02bdee03b57985 (diff)
ASoC/mpc5200: fix enable/disable of AC97 slots
The MPC5200 AC97 driver is disabling the slots when a stop trigger is received, but not reenabling them if the stream is started again without processing the hw_params again. This patch fixes the problem by caching the slot enable bit settings calculated at hw_params time so that they can be reapplied every time the start trigger is received. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/fsl/mpc5200_dma.h4
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c39
2 files changed, 25 insertions, 18 deletions
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index 956d6a5f5a8c..22208b373fb9 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -16,6 +16,7 @@
16 * @period_end: physical address of end of DMA region 16 * @period_end: physical address of end of DMA region
17 * @period_next_pt: physical address of next DMA buffer to enqueue 17 * @period_next_pt: physical address of next DMA buffer to enqueue
18 * @period_bytes: size of DMA period in bytes 18 * @period_bytes: size of DMA period in bytes
19 * @ac97_slot_bits: Enable bits for turning on the correct AC97 slot
19 */ 20 */
20struct psc_dma_stream { 21struct psc_dma_stream {
21 struct snd_pcm_runtime *runtime; 22 struct snd_pcm_runtime *runtime;
@@ -28,6 +29,9 @@ struct psc_dma_stream {
28 int period_current; 29 int period_current;
29 int period_bytes; 30 int period_bytes;
30 int period_count; 31 int period_count;
32
33 /* AC97 state */
34 u32 ac97_slot_bits;
31}; 35};
32 36
33/** 37/**
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index c4ae3e096bb9..3dbc7f7cd7b9 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -130,6 +130,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
130 struct snd_soc_dai *cpu_dai) 130 struct snd_soc_dai *cpu_dai)
131{ 131{
132 struct psc_dma *psc_dma = cpu_dai->private_data; 132 struct psc_dma *psc_dma = cpu_dai->private_data;
133 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
133 134
134 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 135 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
135 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i" 136 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
@@ -140,20 +141,10 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
140 params_channels(params), params_rate(params), 141 params_channels(params), params_rate(params),
141 params_format(params)); 142 params_format(params));
142 143
143 144 /* Determine the set of enable bits to turn on */
144 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { 145 s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300;
145 if (params_channels(params) == 1) 146 if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE)
146 psc_dma->slots |= 0x00000100; 147 s->ac97_slot_bits <<= 16;
147 else
148 psc_dma->slots |= 0x00000300;
149 } else {
150 if (params_channels(params) == 1)
151 psc_dma->slots |= 0x01000000;
152 else
153 psc_dma->slots |= 0x03000000;
154 }
155 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
156
157 return 0; 148 return 0;
158} 149}
159 150
@@ -163,6 +154,8 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
163{ 154{
164 struct psc_dma *psc_dma = cpu_dai->private_data; 155 struct psc_dma *psc_dma = cpu_dai->private_data;
165 156
157 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);
158
166 if (params_channels(params) == 1) 159 if (params_channels(params) == 1)
167 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000); 160 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
168 else 161 else
@@ -176,14 +169,24 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
176{ 169{
177 struct snd_soc_pcm_runtime *rtd = substream->private_data; 170 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 171 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
172 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
179 173
180 switch (cmd) { 174 switch (cmd) {
175 case SNDRV_PCM_TRIGGER_START:
176 dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n",
177 substream->pstr->stream);
178
179 /* Set the slot enable bits */
180 psc_dma->slots |= s->ac97_slot_bits;
181 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
182 break;
183
181 case SNDRV_PCM_TRIGGER_STOP: 184 case SNDRV_PCM_TRIGGER_STOP:
182 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) 185 dev_dbg(psc_dma->dev, "AC97 STOP: stream=%i\n",
183 psc_dma->slots &= 0xFFFF0000; 186 substream->pstr->stream);
184 else
185 psc_dma->slots &= 0x0000FFFF;
186 187
188 /* Clear the slot enable bits */
189 psc_dma->slots &= ~(s->ac97_slot_bits);
187 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots); 190 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
188 break; 191 break;
189 } 192 }