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 --- |