aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap/omap-pcm.c
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2009-08-10 04:50:04 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-17 05:59:59 -0400
commit64844a6ac8ddd586cb832fea7cf2e93e5e7e03f4 (patch)
tree478fccc70ac7a17861e449438683c22130335e0e /sound/soc/omap/omap-pcm.c
parent1e97f50b7023cda00cb720e53b9e59c250cb4ed7 (diff)
ASoC: OMAP: Make use of DMA channel self linking on OMAP1510
Use newly implemented DMA channel self linking on OMAP1510 like on other OMAP models. Remove unnecessary DMA transfer restart from interrupt handler routine. The interrupt routine used to maintain a period index, originally needed for counting up periods up to a full buffer in order to restart the DMA transfer. For some time, this counter is also used as a replacement for hardware DMA progress counter that has been found unusable on OMAP1510 in case of playback. Thus, the period index calculation cannot be omitted completely. However, the accuracy of this counter can still suffer from missing DMA interrupts. In order to work correctly, it requires patch 1 from this series also applied: [RFC][PATCH 1/3] ARM: OMAP: DMA: Add support for DMA channel self linking on OMAP1510 Created against linux-2.6.31-rc5. Tested on Amstrad Delta. Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/omap/omap-pcm.c')
-rw-r--r--sound/soc/omap/omap-pcm.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index c3c931d4537a..3e3a9d478c0d 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -59,16 +59,18 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
59 struct omap_runtime_data *prtd = runtime->private_data; 59 struct omap_runtime_data *prtd = runtime->private_data;
60 unsigned long flags; 60 unsigned long flags;
61 61
62 if (cpu_is_omap1510()) { 62 if ((cpu_is_omap1510()) &&
63 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
63 /* 64 /*
64 * OMAP1510 doesn't support DMA chaining so have to restart 65 * OMAP1510 doesn't fully support DMA progress counter
65 * the transfer after all periods are transferred 66 * and there is no software emulation implemented yet,
67 * so have to maintain our own playback progress counter
68 * that can be used by omap_pcm_pointer() instead.
66 */ 69 */
67 spin_lock_irqsave(&prtd->lock, flags); 70 spin_lock_irqsave(&prtd->lock, flags);
68 if (prtd->period_index >= 0) { 71 if (prtd->period_index >= 0) {
69 if (++prtd->period_index == runtime->periods) { 72 if (++prtd->period_index == runtime->periods) {
70 prtd->period_index = 0; 73 prtd->period_index = 0;
71 omap_start_dma(prtd->dma_ch);
72 } 74 }
73 } 75 }
74 spin_unlock_irqrestore(&prtd->lock, flags); 76 spin_unlock_irqrestore(&prtd->lock, flags);
@@ -100,7 +102,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
100 prtd->dma_data = dma_data; 102 prtd->dma_data = dma_data;
101 err = omap_request_dma(dma_data->dma_req, dma_data->name, 103 err = omap_request_dma(dma_data->dma_req, dma_data->name,
102 omap_pcm_dma_irq, substream, &prtd->dma_ch); 104 omap_pcm_dma_irq, substream, &prtd->dma_ch);
103 if (!err && !cpu_is_omap1510()) { 105 if (!err) {
104 /* 106 /*
105 * Link channel with itself so DMA doesn't need any 107 * Link channel with itself so DMA doesn't need any
106 * reprogramming while looping the buffer 108 * reprogramming while looping the buffer
@@ -119,8 +121,7 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
119 if (prtd->dma_data == NULL) 121 if (prtd->dma_data == NULL)
120 return 0; 122 return 0;
121 123
122 if (!cpu_is_omap1510()) 124 omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
123 omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
124 omap_free_dma(prtd->dma_ch); 125 omap_free_dma(prtd->dma_ch);
125 prtd->dma_data = NULL; 126 prtd->dma_data = NULL;
126 127