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>

Ben Dooks e3d80248 964fe080

+27 -2
+7
arch/arm/mach-s3c2410/include/mach/dma.h
··· 110 110 * waiting for reloads */ 111 111 #define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */ 112 112 113 + #define S3C2410_DMAF_CIRCULAR (1 << 2) /* no circular dma support */ 114 + 113 115 /* dma buffer */ 114 116 115 117 struct s3c2410_dma_buf; ··· 195 193 }; 196 194 197 195 typedef unsigned long dma_device_t; 196 + 197 + static inline bool s3c_dma_has_circular(void) 198 + { 199 + return false; 200 + } 198 201 199 202 #endif /* __ASM_ARCH_DMA_H */
+5
arch/arm/mach-s3c6400/include/mach/dma.h
··· 68 68 69 69 #define S3C2410_DMAF_CIRCULAR (1 << 0) 70 70 71 + static inline bool s3c_dma_has_circular(void) 72 + { 73 + return false; 74 + } 75 + 71 76 #include <plat/dma.h> 72 77 73 78 #endif /* __ASM_ARCH_IRQ_H */
+15 -2
sound/soc/s3c24xx/s3c24xx-pcm.c
··· 75 75 { 76 76 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 77 77 dma_addr_t pos = prtd->dma_pos; 78 + unsigned int limit; 78 79 int ret; 79 80 80 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 91 unsigned long len = prtd->dma_period; 84 92 85 93 pr_debug("dma_loaded: %d\n", prtd->dma_loaded); ··· 131 123 snd_pcm_period_elapsed(substream); 132 124 133 125 spin_lock(&prtd->lock); 134 - if (prtd->state & ST_RUNNING) { 126 + if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) { 135 127 prtd->dma_loaded--; 136 128 s3c24xx_pcm_enqueue(substream); 137 129 } ··· 172 164 printk(KERN_ERR "failed to get dma channel\n"); 173 165 return ret; 174 166 } 167 + 168 + /* use the circular buffering if we have it available. */ 169 + if (s3c_dma_has_circular()) 170 + s3c2410_dma_setflags(prtd->params->channel, 171 + S3C2410_DMAF_CIRCULAR); 175 172 } 176 173 177 174 s3c2410_dma_set_buffdone_fn(prtd->params->channel,