diff options
author | Ben Dooks <ben-linux@fluff.org> | 2009-09-22 11:48:56 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2009-10-28 14:22:57 -0400 |
commit | e3d8024891dbfec6cf36c9b76177650f48118462 (patch) | |
tree | 2046fa2ec4259e32b02ef29107fa6ace142e8f8f /sound | |
parent | 964fe080d94db82a3268443e9b9ece4c60246414 (diff) |
ARM: S3C: Add info for supporting circular DMA buffers
The S3C64XX DMA implementation will work a lot better with the ability
to enqueue circular buffers as the hardware can do it's own linked-list
management.
Add a function s3c_dma_has_circular() to show that the system can do this
and a flag for the channel.
Update the s3c24xx/s3c64xx I2S DMA code to deal with this.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Acked-by: Mark Brown <broonie@@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/s3c24xx/s3c24xx-pcm.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c index 5cbbdc80fde3..1f35c6fcf5fd 100644 --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c | |||
@@ -75,11 +75,19 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) | |||
75 | { | 75 | { |
76 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 76 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; |
77 | dma_addr_t pos = prtd->dma_pos; | 77 | dma_addr_t pos = prtd->dma_pos; |
78 | unsigned int limit; | ||
78 | int ret; | 79 | int ret; |
79 | 80 | ||
80 | pr_debug("Entered %s\n", __func__); | 81 | pr_debug("Entered %s\n", __func__); |
81 | 82 | ||
82 | while (prtd->dma_loaded < prtd->dma_limit) { | 83 | if (s3c_dma_has_circular()) { |
84 | limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; | ||
85 | } else | ||
86 | limit = prtd->dma_limit; | ||
87 | |||
88 | pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit); | ||
89 | |||
90 | while (prtd->dma_loaded < limit) { | ||
83 | unsigned long len = prtd->dma_period; | 91 | unsigned long len = prtd->dma_period; |
84 | 92 | ||
85 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); | 93 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); |
@@ -123,7 +131,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel, | |||
123 | snd_pcm_period_elapsed(substream); | 131 | snd_pcm_period_elapsed(substream); |
124 | 132 | ||
125 | spin_lock(&prtd->lock); | 133 | spin_lock(&prtd->lock); |
126 | if (prtd->state & ST_RUNNING) { | 134 | if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) { |
127 | prtd->dma_loaded--; | 135 | prtd->dma_loaded--; |
128 | s3c24xx_pcm_enqueue(substream); | 136 | s3c24xx_pcm_enqueue(substream); |
129 | } | 137 | } |
@@ -164,6 +172,11 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
164 | printk(KERN_ERR "failed to get dma channel\n"); | 172 | printk(KERN_ERR "failed to get dma channel\n"); |
165 | return ret; | 173 | return ret; |
166 | } | 174 | } |
175 | |||
176 | /* use the circular buffering if we have it available. */ | ||
177 | if (s3c_dma_has_circular()) | ||
178 | s3c2410_dma_setflags(prtd->params->channel, | ||
179 | S3C2410_DMAF_CIRCULAR); | ||
167 | } | 180 | } |
168 | 181 | ||
169 | s3c2410_dma_set_buffdone_fn(prtd->params->channel, | 182 | s3c2410_dma_set_buffdone_fn(prtd->params->channel, |