mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
rk30: support sound capture DMA buffer in internal SRAM
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user