From 86ee81f2ac6db71eaf531881a68941e6f64cf98a Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=82=B1=E5=BB=BA=E6=96=8C?= Date: Sat, 2 Feb 2013 12:07:11 +0800 Subject: [PATCH] audio/i2s : i2s dma infiniteloop support --- sound/soc/rk29/rk29_pcm.c | 110 +++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/sound/soc/rk29/rk29_pcm.c b/sound/soc/rk29/rk29_pcm.c index 072aeb713360..c28bfc69cff5 100755 --- a/sound/soc/rk29/rk29_pcm.c +++ b/sound/soc/rk29/rk29_pcm.c @@ -31,11 +31,17 @@ #define PCM_DMA_DEBUG 0 #if 0 -#define DBG(x...) printk(KERN_DEBUG x) +#define DBG(x...) printk(KERN_INFO x) #else #define DBG(x...) do { } while (0) #endif +#define INFIN_LOOP +#ifdef INFIN_LOOP +#define DMA_INFIN_LOOP() rk29_dma_has_infiniteloop() +#else +#define DMA_INFIN_LOOP() 0 +#endif static const struct snd_pcm_hardware rockchip_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | @@ -97,46 +103,67 @@ static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream) { struct rockchip_runtime_data *prtd = substream->runtime->private_data; dma_addr_t pos = prtd->dma_pos; + unsigned int limit; int ret; -// DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - while (prtd->dma_loaded < prtd->dma_limit) { - unsigned long len = prtd->dma_period; -// DBG("dma_loaded: %d\n", prtd->dma_loaded); - if ((pos + len) > prtd->dma_end) { - len = prtd->dma_end - pos; - } + printk("Enter::%s----%d prtd->dma_period = %d prtd->dma_limit = %d\n",__FUNCTION__,__LINE__,prtd->dma_period,prtd->dma_limit); - if((len%(prtd->params->dma_size*16) == 0) && (prtd->params->flag == 1)) - { - ret = rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 16); - prtd->params->flag = 0; - DBG("size = 16, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); - } - else if((len%(prtd->params->dma_size*16) != 0) && (prtd->params->flag == 0)) - { - ret = rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 1); - prtd->params->flag = 1; - DBG("size = 1, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); + if (rk29_dma_has_circular()) + limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; + else + limit = prtd->dma_limit; + + if (DMA_INFIN_LOOP()) { + if(prtd->dma_period % prtd->params->dma_size*16){ + WARN_ON(1); + rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 1); + } + else + rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 16); + + ret = rk29_dma_enqueue_ring(prtd->params->channel, + substream, pos, prtd->dma_period, limit ,true); + if (ret == 0) + pos = prtd->dma_start; + } else { + while (prtd->dma_loaded < prtd->dma_limit) { + unsigned long len = prtd->dma_period; + // DBG("dma_loaded: %d\n", prtd->dma_loaded); + if ((pos + len) > prtd->dma_end) { + len = prtd->dma_end - pos; + } + + if((len%(prtd->params->dma_size*16) == 0) && (prtd->params->flag == 1)) + { + ret = rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 16); + prtd->params->flag = 0; + DBG("size = 16, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); + } + else if((len%(prtd->params->dma_size*16) != 0) && (prtd->params->flag == 0)) + { + ret = rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 1); + prtd->params->flag = 1; + DBG("size = 1, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); + } + + + ret = rk29_dma_enqueue(prtd->params->channel,substream, pos, len); + // if(prtd->params->channel == 2) + DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X, Len=%lu\n", + __FUNCTION__,__LINE__, ret, prtd->params->channel, pos, len); + if (ret == 0) { + prtd->dma_loaded++; + pos += prtd->dma_period; + if (pos >= prtd->dma_end) + pos = prtd->dma_start; + } else + break; } - - - ret = rk29_dma_enqueue(prtd->params->channel,substream, pos, len); -// if(prtd->params->channel == 2) - DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X, Len=%lu\n", - __FUNCTION__,__LINE__, ret, prtd->params->channel, pos, len); - if (ret == 0) { - prtd->dma_loaded++; - pos += prtd->dma_period; - if (pos >= prtd->dma_end) - pos = prtd->dma_start; - } else - break; } - prtd->dma_pos = pos; } @@ -153,7 +180,7 @@ void rk29_audio_buffdone(void *dev_id, int size, t = ktime_to_us(ktime_sub(after, before)); if(result == RK29_RES_OK) { - if(t > 23220+73 && t != ktime_to_us(after)) // 4096/4/44100 + 32/44100 + if(t > prtd->dma_period/4/44100 +73 && t != ktime_to_us(after)) // (23220)4096/4/44100 + 32/44100 { printk(KERN_DEBUG "Time out:: Audio DMA buffdone time out!!! the time = %lld!\n", t); } @@ -184,19 +211,18 @@ void rk29_audio_buffdone(void *dev_id, int size, prtd = substream->runtime->private_data; // if(prtd->params->channel == 2) - DBG("Enter::%s----%d channel =%d \n",__FUNCTION__,__LINE__); + DBG("Enter::%s----%d channel =%d \n",__FUNCTION__,__LINE__,prtd->params->channel); if(!(prtd->state & ST_RUNNING)) return; if (substream){ snd_pcm_period_elapsed(substream); } spin_lock(&prtd->lock); - prtd->dma_loaded--; - if (prtd->state & ST_RUNNING) { + if (!DMA_INFIN_LOOP() && prtd->state & ST_RUNNING) { + prtd->dma_loaded--; rockchip_pcm_enqueue(substream); } - spin_unlock(&prtd->lock); - + spin_unlock(&prtd->lock); } static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream, -- 2.34.1