rk30: support sound capture DMA buffer in internal SRAM
author邱建斌 <qjb@rock-chips.com>
Thu, 7 Jun 2012 08:53:04 +0000 (16:53 +0800)
committer邱建斌 <qjb@rock-chips.com>
Thu, 7 Jun 2012 08:53:04 +0000 (16:53 +0800)
arch/arm/plat-rk/Kconfig
sound/soc/rk29/rk29_pcm.c

index c02435d6cb14acb1b0409e463ad8f964f9551177..feeb4da065c11ba34ad90d0f0e03d9e957c78627 100644 (file)
@@ -133,7 +133,7 @@ config RK_DEBUG_UART
          Select a UART for debugging. -1 disable.
 
 config RK_SRAM_DMA
-       bool "Sound playback DMA buffer in internal SRAM"
+       bool "Sound DMA buffer in internal SRAM"
        depends on ARCH_RK30
 
 endif
index 048038077c6233916796015e5455c0ab967cf407..20b21e391f3d9f808923ceb1cac8fa1142163e06 100755 (executable)
@@ -31,7 +31,7 @@
 #define PCM_DMA_DEBUG 0
 
 #if 0
-#define DBG(x...) printk(KERN_INFO x)
+#define DBG(x...) printk(KERN_DEBUG x)
 #else
 #define DBG(x...) do { } while (0)
 #endif
@@ -50,13 +50,13 @@ static const struct snd_pcm_hardware rockchip_pcm_hardware = {
        .channels_min           = 2,
        .channels_max           = 8,
 #ifdef CONFIG_RK_SRAM_DMA
-       .buffer_bytes_max       = 48*1024,
+       .buffer_bytes_max       = 24*1024,//period_bytes_max * periods_max
 #else
        .buffer_bytes_max       = 128*1024,
 #endif
        .period_bytes_min       = 64,  ///PAGE_SIZE,
 #ifdef CONFIG_RK_SRAM_DMA
-       .period_bytes_max       = 4096*4,
+       .period_bytes_max       = 8*1024,
 #else
        .period_bytes_max       = 2048*4,///PAGE_SIZE*2,
 #endif
@@ -99,12 +99,11 @@ static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream)
        dma_addr_t pos = prtd->dma_pos;
        int ret;
 
-        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+//     DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
         
-        while (prtd->dma_loaded < prtd->dma_limit) {
+       while (prtd->dma_loaded < prtd->dma_limit) {
                unsigned long len = prtd->dma_period;
-               
-                DBG("dma_loaded: %d\n", prtd->dma_loaded);
+//     DBG("dma_loaded: %d\n", prtd->dma_loaded);
                if ((pos + len) > prtd->dma_end) {
                        len  = prtd->dma_end - pos;
                }
@@ -125,11 +124,10 @@ static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream)
                }
 
 
-               ret = rk29_dma_enqueue(prtd->params->channel, 
-                       substream, pos, len);
-                
-                DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X, Len=%lu\n",
-                        __FUNCTION__,__LINE__, ret, prtd->params->channel, pos, len);                  
+               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;
@@ -145,7 +143,7 @@ static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream)
 void rk29_audio_buffdone(void *dev_id, int size,
                                   enum rk29_dma_buffresult result)
 {
-        struct snd_pcm_substream *substream = dev_id;
+       struct snd_pcm_substream *substream = dev_id;
        struct rockchip_runtime_data *prtd;
 #if PCM_DMA_DEBUG
        static ktime_t before = {0},after = {0};
@@ -165,27 +163,30 @@ void rk29_audio_buffdone(void *dev_id, int size,
 #endif
        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
        
-       if (!substream)
+       if (!substream){
+               DBG("substream is free\n");
                return;
-       if (!substream->runtime)
+       }       
+       if (!substream->runtime){
+               DBG("substream->runtime is free\n");
                return;
+       }       
        switch(result)
        {
        case RK29_RES_OK:
-               DBG("::%s----%d  RK29_RES_OK\n",__FUNCTION__,__LINE__);
                break;
        case RK29_RES_ERR:
-               DBG("::%s----%d  RK29_RES_ERR\n",__FUNCTION__,__LINE__);
-               break;
        case RK29_RES_ABORT:
-               DBG("Enter::%s----%d RK29_RES_ABORT \n",__FUNCTION__,__LINE__);
+               DBG("Enter::%s dma about or error result = %d \n",__FUNCTION__,result);
                return;
        }
 
        prtd = substream->runtime->private_data;
+       
+//     if(prtd->params->channel == 2)
+               DBG("Enter::%s----%d   channel =%d \n",__FUNCTION__,__LINE__);  
        if(!(prtd->state & ST_RUNNING))
                return; 
-       DBG("Enter::%s----%d, substream=%p, prtd=%p\n",__FUNCTION__,__LINE__, substream, prtd);
        if (substream){
                snd_pcm_period_elapsed(substream);
        }
@@ -215,15 +216,6 @@ static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
        int ret = 0;
 
        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-       /*by Vincent Hsiung for EQ Vol Change*/
-       #define HW_PARAMS_FLAG_EQVOL_ON 0x21
-       #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
-
-        if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
-       {
-               return 0;
-       }
-
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
        if (!dma)
@@ -235,19 +227,9 @@ static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
                /* prepare DMA */
                prtd->params = dma;
 #ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC
-               DBG("params %p, client %p, channel %d\n", prtd->params,
-                       prtd->params->client, prtd->params->channel);
-
-                ret = rk29_dma_request(prtd->params->channel, prtd->params->client, NULL);
-                DBG("Enter::%s, %d, ret=%d, Channel=%d\n", __FUNCTION__, __LINE__, ret, prtd->params->channel);
-/*
-                if(ret){
-                       for(prtd->params->channel=5;prtd->params->channel>0;prtd->params->channel--){
-                               ret = request_dma(prtd->params->channel, "i2s");
-                               if(!ret)break;
-                       }
-               }
-*/             
+               DBG("params %p, client %p, channel %d\n", prtd->params,prtd->params->client, prtd->params->channel);
+               ret = rk29_dma_request(prtd->params->channel, prtd->params->client, NULL);
+               DBG("Enter::%s, %d, ret=%d, Channel=%d\n", __FUNCTION__, __LINE__, ret, prtd->params->channel);
                if (ret) {
                        DBG(KERN_ERR "failed to get dma channel\n");
                        return ret;
@@ -255,15 +237,18 @@ static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
 #endif
        }
 
-        rk29_dma_set_buffdone_fn(prtd->params->channel, rk29_audio_buffdone);
-
+       ret = rk29_dma_set_buffdone_fn(prtd->params->channel, rk29_audio_buffdone);
+       if(ret < 0){
+               DBG(KERN_ERR "failed to rk29_dma_set_buffdone_fn\n");
+               return ret;
+       }
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        runtime->dma_bytes = totbytes;
 
        spin_lock_irq(&prtd->lock);
        prtd->dma_loaded = 0;
-       prtd->dma_limit = runtime->hw.periods_min;
+       prtd->dma_limit = params_periods(params);//runtime->hw.periods_min;
        prtd->dma_period = params_period_bytes(params);
        prtd->dma_start = runtime->dma_addr;
        prtd->dma_pos = prtd->dma_start;
@@ -273,7 +258,7 @@ static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
        prtd->next = NULL;
        prtd->end = NULL;
        spin_unlock_irq(&prtd->lock);
-       return 0;
+       return ret;
 }
 
 static int rockchip_pcm_hw_free(struct snd_pcm_substream *substream)
@@ -406,10 +391,10 @@ rockchip_pcm_pointer(struct snd_pcm_substream *substream)
        dma_addr_t src, dst;
        snd_pcm_uframes_t ret;
     
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+
        spin_lock(&prtd->lock);
 
-        rk29_dma_getposition(prtd->params->channel, &src, &dst);
+       rk29_dma_getposition(prtd->params->channel, &src, &dst);
        
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
                res = dst - prtd->dma_start;
@@ -418,11 +403,13 @@ rockchip_pcm_pointer(struct snd_pcm_substream *substream)
 
        spin_unlock(&prtd->lock);
 
-       DBG("Pointer %x %x\n",src,dst); 
-
        ret = bytes_to_frames(runtime, res);
        if (ret == runtime->buffer_size)
                ret = 0;
+               
+       if(prtd->params->channel == 2)          
+               DBG("Enter:%s src = %x res = %x ret = %d\n",__FUNCTION__,src,res,ret);  
+
        return ret;     
 }
 
@@ -501,8 +488,10 @@ static struct snd_pcm_ops rockchip_pcm_ops = {
 };
 
 #ifdef CONFIG_ARCH_RK30
-#define SRAM_DMA_PHYS  (dma_addr_t)(RK30_IMEM_PHYS + 16*1024)
-#define SRAM_DMA_START (RK30_IMEM_NONCACHED + 16*1024)
+#define SRAM_DMA_PHYS_PLAYBACK (dma_addr_t)(RK30_IMEM_PHYS + 16*1024)
+#define SRAM_DMA_START_PLAYBACK        (RK30_IMEM_NONCACHED + 16*1024)
+#define SRAM_DMA_PHYS_CAPTURE  (dma_addr_t)(SRAM_DMA_PHYS_PLAYBACK + 24*1024)
+#define SRAM_DMA_START_CAPTURE (SRAM_DMA_START_PLAYBACK + 24*1024)
 #endif
 
 static int rockchip_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
@@ -518,12 +507,16 @@ static int rockchip_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        buf->private_data = NULL;
 #ifdef CONFIG_RK_SRAM_DMA
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               buf->area = SRAM_DMA_START;
-               buf->addr = SRAM_DMA_PHYS;
-       } else
-#endif
+               buf->area = SRAM_DMA_START_PLAYBACK;
+               buf->addr = SRAM_DMA_PHYS_PLAYBACK;
+       } else{
+               buf->area = SRAM_DMA_START_CAPTURE;
+               buf->addr = SRAM_DMA_PHYS_CAPTURE;              
+       }
+#else
        buf->area = dma_alloc_writecombine(pcm->card->dev, size,
                                           &buf->addr, GFP_KERNEL);
+#endif
        if (!buf->area)
                return -ENOMEM;
        buf->bytes = size;