diff options
author | Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> | 2010-03-28 16:29:29 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-04-02 12:10:25 -0400 |
commit | b5442a75deee293d10c2ab8f4a77013973c4c9e0 (patch) | |
tree | 5741e9c0cb9f8e71b3f92b1145e166716579155a /sound | |
parent | fb48e3c6a4d8888aff61fbf567aadac7d206e973 (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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/omap/omap-pcm.c | 17 |
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; |