aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2010-03-28 16:29:29 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-04-02 12:10:25 -0400
commitb5442a75deee293d10c2ab8f4a77013973c4c9e0 (patch)
tree5741e9c0cb9f8e71b3f92b1145e166716579155a
parentfb48e3c6a4d8888aff61fbf567aadac7d206e973 (diff)
ASoC: OMAP: Fix capture pointer handling for OMAP1510 to work correctly with recent ALSA PCM code
With recent (2.6.34) chnages in PCM handling, capture stopped working on my OMAP1510 based Amstrad Delta videophone. Using 2.6.34-rc2, I was able to correct the problem in 3 different ways: 1. reverting commit 7b3a177b0d4f92b3431b8dca777313a07533a710, 2. enabling additional jiffies check with echo 4 >/proc/asound/card0/pcm0c0/xrun_debug 3. applying the patch below. Since I wasn't able to reproduce the problem on my i686 PC, I guess the problem is probably machine specific. The patch reuses the method for software emulation of missing hardware pointer, already implemented for playback on OMAP1510. It's possible that event if a hardware pointer is available for capture on this machine, its behaviour may be not compatible with what upper layer expects. If you think the problem may be more general and should be solved differently, on a higher level, I can try to work more on it if you give me a hint. If the patch gets accepted, I suggest it goes as a fix in the current release cycle. Created and tested against linux-2.6.34-rc2. Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/omap/omap-pcm.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 825db385f01f..bdd1097c7b13 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -60,12 +60,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
60 struct omap_runtime_data *prtd = runtime->private_data; 60 struct omap_runtime_data *prtd = runtime->private_data;
61 unsigned long flags; 61 unsigned long flags;
62 62
63 if ((cpu_is_omap1510()) && 63 if ((cpu_is_omap1510())) {
64 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
65 /* 64 /*
66 * OMAP1510 doesn't fully support DMA progress counter 65 * OMAP1510 doesn't fully support DMA progress counter
67 * and there is no software emulation implemented yet, 66 * and there is no software emulation implemented yet,
68 * so have to maintain our own playback progress counter 67 * so have to maintain our own progress counters
69 * that can be used by omap_pcm_pointer() instead. 68 * that can be used by omap_pcm_pointer() instead.
70 */ 69 */
71 spin_lock_irqsave(&prtd->lock, flags); 70 spin_lock_irqsave(&prtd->lock, flags);
@@ -189,8 +188,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
189 dma_params.frame_count = runtime->periods; 188 dma_params.frame_count = runtime->periods;
190 omap_set_dma_params(prtd->dma_ch, &dma_params); 189 omap_set_dma_params(prtd->dma_ch, &dma_params);
191 190
192 if ((cpu_is_omap1510()) && 191 if ((cpu_is_omap1510()))
193 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
194 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | 192 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
195 OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); 193 OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
196 else 194 else
@@ -248,14 +246,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
248 dma_addr_t ptr; 246 dma_addr_t ptr;
249 snd_pcm_uframes_t offset; 247 snd_pcm_uframes_t offset;
250 248
251 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 249 if (cpu_is_omap1510()) {
250 offset = prtd->period_index * runtime->period_size;
251 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
252 ptr = omap_get_dma_dst_pos(prtd->dma_ch); 252 ptr = omap_get_dma_dst_pos(prtd->dma_ch);
253 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); 253 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
254 } else if (!(cpu_is_omap1510())) { 254 } else {
255 ptr = omap_get_dma_src_pos(prtd->dma_ch); 255 ptr = omap_get_dma_src_pos(prtd->dma_ch);
256 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); 256 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
257 } else 257 }
258 offset = prtd->period_index * runtime->period_size;
259 258
260 if (offset >= runtime->buffer_size) 259 if (offset >= runtime->buffer_size)
261 offset = 0; 260 offset = 0;