rk30: support sound capture DMA buffer in internal SRAM

This commit is contained in:
邱建斌
2012-06-07 16:53:04 +08:00
parent aa24220245
commit 8971e7babe
2 changed files with 50 additions and 57 deletions

View 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

View File

@@ -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;