diff options
Diffstat (limited to 'sound/soc/kirkwood/kirkwood-i2s.c')
-rw-r--r-- | sound/soc/kirkwood/kirkwood-i2s.c | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 542538d10ab7..1d5db484d2df 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) | |||
95 | do { | 95 | do { |
96 | cpu_relax(); | 96 | cpu_relax(); |
97 | value = readl(io + KIRKWOOD_DCO_SPCR_STATUS); | 97 | value = readl(io + KIRKWOOD_DCO_SPCR_STATUS); |
98 | value &= KIRKWOOD_DCO_SPCR_STATUS; | 98 | value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK; |
99 | } while (value == 0); | 99 | } while (value == 0); |
100 | } | 100 | } |
101 | 101 | ||
@@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
180 | int cmd, struct snd_soc_dai *dai) | 180 | int cmd, struct snd_soc_dai *dai) |
181 | { | 181 | { |
182 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | 182 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); |
183 | unsigned long value; | 183 | uint32_t ctl, value; |
184 | 184 | ||
185 | /* | 185 | ctl = readl(priv->io + KIRKWOOD_PLAYCTL); |
186 | * specs says KIRKWOOD_PLAYCTL must be read 2 times before | 186 | if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { |
187 | * changing it. So read 1 time here and 1 later. | 187 | unsigned timeout = 5000; |
188 | */ | 188 | /* |
189 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 189 | * The Armada510 spec says that if we enter pause mode, the |
190 | * busy bit must be read back as clear _twice_. Make sure | ||
191 | * we respect that otherwise we get DMA underruns. | ||
192 | */ | ||
193 | do { | ||
194 | value = ctl; | ||
195 | ctl = readl(priv->io + KIRKWOOD_PLAYCTL); | ||
196 | if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)) | ||
197 | break; | ||
198 | udelay(1); | ||
199 | } while (timeout--); | ||
200 | |||
201 | if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) | ||
202 | dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", | ||
203 | ctl); | ||
204 | } | ||
190 | 205 | ||
191 | switch (cmd) { | 206 | switch (cmd) { |
192 | case SNDRV_PCM_TRIGGER_START: | 207 | case SNDRV_PCM_TRIGGER_START: |
193 | /* stop audio, enable interrupts */ | ||
194 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | ||
195 | value |= KIRKWOOD_PLAYCTL_PAUSE; | ||
196 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | ||
197 | |||
198 | value = readl(priv->io + KIRKWOOD_INT_MASK); | 208 | value = readl(priv->io + KIRKWOOD_INT_MASK); |
199 | value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; | 209 | value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; |
200 | writel(value, priv->io + KIRKWOOD_INT_MASK); | 210 | writel(value, priv->io + KIRKWOOD_INT_MASK); |
201 | 211 | ||
202 | /* configure audio & enable i2s playback */ | 212 | /* configure audio & enable i2s playback */ |
203 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 213 | ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK; |
204 | value &= ~KIRKWOOD_PLAYCTL_BURST_MASK; | 214 | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
205 | value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | ||
206 | | KIRKWOOD_PLAYCTL_SPDIF_EN); | 215 | | KIRKWOOD_PLAYCTL_SPDIF_EN); |
207 | 216 | ||
208 | if (priv->burst == 32) | 217 | if (priv->burst == 32) |
209 | value |= KIRKWOOD_PLAYCTL_BURST_32; | 218 | ctl |= KIRKWOOD_PLAYCTL_BURST_32; |
210 | else | 219 | else |
211 | value |= KIRKWOOD_PLAYCTL_BURST_128; | 220 | ctl |= KIRKWOOD_PLAYCTL_BURST_128; |
212 | value |= KIRKWOOD_PLAYCTL_I2S_EN; | 221 | ctl |= KIRKWOOD_PLAYCTL_I2S_EN; |
213 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 222 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
214 | break; | 223 | break; |
215 | 224 | ||
216 | case SNDRV_PCM_TRIGGER_STOP: | 225 | case SNDRV_PCM_TRIGGER_STOP: |
217 | /* stop audio, disable interrupts */ | 226 | /* stop audio, disable interrupts */ |
218 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 227 | ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; |
219 | value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; | 228 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
220 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | ||
221 | 229 | ||
222 | value = readl(priv->io + KIRKWOOD_INT_MASK); | 230 | value = readl(priv->io + KIRKWOOD_INT_MASK); |
223 | value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; | 231 | value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; |
224 | writel(value, priv->io + KIRKWOOD_INT_MASK); | 232 | writel(value, priv->io + KIRKWOOD_INT_MASK); |
225 | 233 | ||
226 | /* disable all playbacks */ | 234 | /* disable all playbacks */ |
227 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 235 | ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); |
228 | value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); | 236 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
229 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | ||
230 | break; | 237 | break; |
231 | 238 | ||
232 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 239 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
233 | case SNDRV_PCM_TRIGGER_SUSPEND: | 240 | case SNDRV_PCM_TRIGGER_SUSPEND: |
234 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 241 | ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; |
235 | value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; | 242 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
236 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | ||
237 | break; | 243 | break; |
238 | 244 | ||
239 | case SNDRV_PCM_TRIGGER_RESUME: | 245 | case SNDRV_PCM_TRIGGER_RESUME: |
240 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 246 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
241 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 247 | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); |
242 | value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); | 248 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
243 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | ||
244 | break; | 249 | break; |
245 | 250 | ||
246 | default: | 251 | default: |
@@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, | |||
260 | 265 | ||
261 | switch (cmd) { | 266 | switch (cmd) { |
262 | case SNDRV_PCM_TRIGGER_START: | 267 | case SNDRV_PCM_TRIGGER_START: |
263 | /* stop audio, enable interrupts */ | ||
264 | value = readl(priv->io + KIRKWOOD_RECCTL); | ||
265 | value |= KIRKWOOD_RECCTL_PAUSE; | ||
266 | writel(value, priv->io + KIRKWOOD_RECCTL); | ||
267 | |||
268 | value = readl(priv->io + KIRKWOOD_INT_MASK); | 268 | value = readl(priv->io + KIRKWOOD_INT_MASK); |
269 | value |= KIRKWOOD_INT_CAUSE_REC_BYTES; | 269 | value |= KIRKWOOD_INT_CAUSE_REC_BYTES; |
270 | writel(value, priv->io + KIRKWOOD_INT_MASK); | 270 | writel(value, priv->io + KIRKWOOD_INT_MASK); |