kirkwood-i2s.c (2424d458108e275ca736dabc792ee9b6733994c5) kirkwood-i2s.c (982b604bc56a3da874e489051fc7adb49b1eba65)
1/*
2 * kirkwood-i2s.c
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the

--- 166 unchanged lines hidden (view full) ---

175
176 return 0;
177}
178
179static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
180 int cmd, struct snd_soc_dai *dai)
181{
182 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
1/*
2 * kirkwood-i2s.c
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the

--- 166 unchanged lines hidden (view full) ---

175
176 return 0;
177}
178
179static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
180 int cmd, struct snd_soc_dai *dai)
181{
182 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
183 unsigned long value;
183 uint32_t ctl, value;
184
184
185 /*
186 * specs says KIRKWOOD_PLAYCTL must be read 2 times before
187 * changing it. So read 1 time here and 1 later.
188 */
189 value = readl(priv->io + KIRKWOOD_PLAYCTL);
185 ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
186 if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
187 unsigned timeout = 5000;
188 /*
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--);
190
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 }
205
191 switch (cmd) {
192 case SNDRV_PCM_TRIGGER_START:
193 /* stop audio, enable interrupts */
206 switch (cmd) {
207 case SNDRV_PCM_TRIGGER_START:
208 /* stop audio, enable interrupts */
194 value = readl(priv->io + KIRKWOOD_PLAYCTL);
195 value |= KIRKWOOD_PLAYCTL_PAUSE;
196 writel(value, priv->io + KIRKWOOD_PLAYCTL);
209 ctl |= KIRKWOOD_PLAYCTL_PAUSE;
210 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
197
198 value = readl(priv->io + KIRKWOOD_INT_MASK);
199 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
200 writel(value, priv->io + KIRKWOOD_INT_MASK);
201
202 /* configure audio & enable i2s playback */
211
212 value = readl(priv->io + KIRKWOOD_INT_MASK);
213 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
214 writel(value, priv->io + KIRKWOOD_INT_MASK);
215
216 /* configure audio & enable i2s playback */
203 value = readl(priv->io + KIRKWOOD_PLAYCTL);
204 value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
205 value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
217 ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
218 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
206 | KIRKWOOD_PLAYCTL_SPDIF_EN);
207
208 if (priv->burst == 32)
219 | KIRKWOOD_PLAYCTL_SPDIF_EN);
220
221 if (priv->burst == 32)
209 value |= KIRKWOOD_PLAYCTL_BURST_32;
222 ctl |= KIRKWOOD_PLAYCTL_BURST_32;
210 else
223 else
211 value |= KIRKWOOD_PLAYCTL_BURST_128;
212 value |= KIRKWOOD_PLAYCTL_I2S_EN;
213 writel(value, priv->io + KIRKWOOD_PLAYCTL);
224 ctl |= KIRKWOOD_PLAYCTL_BURST_128;
225 ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
226 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
214 break;
215
216 case SNDRV_PCM_TRIGGER_STOP:
217 /* stop audio, disable interrupts */
227 break;
228
229 case SNDRV_PCM_TRIGGER_STOP:
230 /* stop audio, disable interrupts */
218 value = readl(priv->io + KIRKWOOD_PLAYCTL);
219 value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
220 writel(value, priv->io + KIRKWOOD_PLAYCTL);
231 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
232 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
221
222 value = readl(priv->io + KIRKWOOD_INT_MASK);
223 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
224 writel(value, priv->io + KIRKWOOD_INT_MASK);
225
226 /* disable all playbacks */
233
234 value = readl(priv->io + KIRKWOOD_INT_MASK);
235 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
236 writel(value, priv->io + KIRKWOOD_INT_MASK);
237
238 /* disable all playbacks */
227 value = readl(priv->io + KIRKWOOD_PLAYCTL);
228 value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
229 writel(value, priv->io + KIRKWOOD_PLAYCTL);
239 ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
240 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
230 break;
231
232 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
233 case SNDRV_PCM_TRIGGER_SUSPEND:
241 break;
242
243 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
244 case SNDRV_PCM_TRIGGER_SUSPEND:
234 value = readl(priv->io + KIRKWOOD_PLAYCTL);
235 value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
236 writel(value, priv->io + KIRKWOOD_PLAYCTL);
245 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
246 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
237 break;
238
239 case SNDRV_PCM_TRIGGER_RESUME:
240 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
247 break;
248
249 case SNDRV_PCM_TRIGGER_RESUME:
250 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
241 value = readl(priv->io + KIRKWOOD_PLAYCTL);
242 value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
243 writel(value, priv->io + KIRKWOOD_PLAYCTL);
251 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
252 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
244 break;
245
246 default:
247 return -EINVAL;
248 }
249
250 return 0;
251}

--- 259 unchanged lines hidden ---
253 break;
254
255 default:
256 return -EINVAL;
257 }
258
259 return 0;
260}

--- 259 unchanged lines hidden ---