1
0
Fork 0

MLK-24501-5 dsp: add lpa pcm support.

Use reserved memory as PCM mode need more memory.
Use ping-pong buffer for PCM LPA playback to avoid underrun.

Signed-off-by: Bing Song <bing.song@nxp.com>
Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Bing Song 2020-08-12 10:22:04 +08:00
parent 5ae911fd64
commit c731ea37ee
6 changed files with 97 additions and 5 deletions

View File

@ -1074,6 +1074,9 @@ static int fsl_dsp_mem_setup_lpa(struct fsl_dsp *dsp_priv)
dsp_priv->scratch_buf_virt = dsp_priv->ocram_vir_addr;
dsp_priv->scratch_buf_phys = dsp_priv->ocram_phys_addr;
dsp_priv->scratch_buf_size = dsp_priv->ocram_reserved_size;
dsp_priv->dram_reserved_vir_addr = dsp_priv->sdram_vir_addr;
dsp_priv->dram_reserved_phys_addr = dsp_priv->sdram_phys_addr;
dsp_priv->dram_reserved_size = dsp_priv->sdram_reserved_size;
dsp_priv->sdram_vir_addr = dsp_priv->regs + SYSRAM_OFFSET;
dsp_priv->sdram_phys_addr = dsp_priv->paddr + SYSRAM_OFFSET;
dsp_priv->sdram_reserved_size = SYSRAM_SIZE;

View File

@ -58,6 +58,8 @@ struct xf_client {
int input_bytes;
int consume_bytes;
int offset;
atomic_t buffer_cnt;
int ping_pong_offset;
};
union xf_client_link {
@ -88,6 +90,9 @@ struct fsl_dsp {
void *sdram_vir_addr;
unsigned long sdram_phys_addr;
int sdram_reserved_size;
void *dram_reserved_vir_addr;
unsigned long dram_reserved_phys_addr;
int dram_reserved_size;
void *ocram_vir_addr;
unsigned long ocram_phys_addr;
int ocram_reserved_size;

View File

@ -33,6 +33,7 @@ void dsp_platform_process(struct work_struct *w)
return;
if (rmsg->opcode == XF_EMPTY_THIS_BUFFER) {
client->consume_bytes += rmsg->length;
atomic_inc(&client->buffer_cnt);
snd_compr_fragment_elapsed(client->cstream);
if (rmsg->buffer == NULL && rmsg->length == 0)
@ -139,6 +140,7 @@ static int dsp_platform_compr_set_params(struct snd_compr_stream *cstream,
switch (params->codec.id) {
case SND_AUDIOCODEC_PCM:
drv->codec_type = CODEC_PCM_DEC;
atomic_set(&drv->client->buffer_cnt, 2);
break;
case SND_AUDIOCODEC_MP3:
drv->codec_type = CODEC_MP3_DEC;
@ -212,6 +214,7 @@ static int dsp_platform_compr_set_params(struct snd_compr_stream *cstream,
drv->client->input_bytes = 0;
drv->client->consume_bytes = 0;
drv->client->offset = 0;
drv->client->ping_pong_offset = 0;
if (drv->codec_type == CODEC_PCM_DEC) {
s_param.id = XA_PCM_CONFIG_PARAM_IN_PCM_WIDTH;
@ -323,6 +326,7 @@ static int dsp_platform_compr_trigger_stop(struct snd_compr_stream *cstream)
drv->client->input_bytes = 0;
drv->client->consume_bytes = 0;
drv->client->offset = 0;
drv->client->ping_pong_offset = 0;
if (!dsp_priv->dsp_is_lpa) {
ret = xaf_comp_delete(drv->client, &drv->component[0]);
@ -438,7 +442,8 @@ static int dsp_platform_compr_pointer(struct snd_compr_stream *cstream,
goto out;
}
if (drv->client->input_bytes != drv->client->consume_bytes)
if ((drv->codec_type != CODEC_PCM_DEC && drv->client->input_bytes != drv->client->consume_bytes)
|| (drv->codec_type == CODEC_PCM_DEC && atomic_read(&drv->client->buffer_cnt) <= 0))
tstamp->copied_total = drv->client->input_bytes+drv->client->offset-4096;
else
tstamp->copied_total = drv->client->input_bytes+drv->client->offset;
@ -492,6 +497,74 @@ static int dsp_platform_compr_copy(struct snd_compr_stream *cstream,
return copied;
}
static int dsp_platform_compr_lpa_pcm_copy(struct snd_compr_stream *cstream,
char __user *buf,
size_t count)
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, FSL_DSP_COMP_NAME);
struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
struct dsp_data *drv = &dsp_priv->dsp_data;
struct xaf_comp *p_comp = &drv->component[0];
int copied = 0;
int ret;
if (atomic_read(&drv->client->buffer_cnt) > 0) {
if (drv->client->offset+count >= (INBUF_SIZE_LPA_PCM>>1)-4096 || !buf) {
/* buf == NULL and count == 1 is for drain and */
/* suspend as tinycompress drain is blocking call */
copied = count;
if (!buf)
copied = 0;
if (buf) {
ret = copy_from_user(p_comp->inptr+drv->client->ping_pong_offset+drv->client->offset, buf, copied);
if (ret) {
dev_err(component->dev, "failed to get message from user space\n");
return -EFAULT;
}
}
if (cstream->runtime->state == SNDRV_PCM_STATE_RUNNING) {
ret = xaf_comp_process(drv->client, p_comp,
p_comp->inptr+drv->client->ping_pong_offset, drv->client->offset+copied,
XF_EMPTY_THIS_BUFFER);
if (!drv->client->input_bytes) {
ret = xaf_connect(drv->client,
&drv->component[0],
&drv->component[1],
1,
OUTBUF_SIZE);
if (ret) {
dev_err(component->dev, "Failed to connect component, err = %d\n", ret);
return ret;
}
}
schedule_work(&drv->client->work);
drv->client->input_bytes += drv->client->offset+copied;
drv->client->offset = 0;
atomic_dec(&drv->client->buffer_cnt);
if (drv->client->ping_pong_offset)
drv->client->ping_pong_offset = 0;
else
drv->client->ping_pong_offset = INBUF_SIZE_LPA_PCM>>1;
}
if (!buf)
copied = count;
} else {
ret = copy_from_user(p_comp->inptr+drv->client->ping_pong_offset+drv->client->offset, buf, count);
if (ret) {
dev_err(component->dev, "failed to get message from user space\n");
return -EFAULT;
}
copied = count;
drv->client->offset += copied;
}
}
return copied;
}
static int dsp_platform_compr_lpa_copy(struct snd_compr_stream *cstream,
char __user *buf,
size_t count)
@ -504,6 +577,9 @@ static int dsp_platform_compr_lpa_copy(struct snd_compr_stream *cstream,
int copied = 0;
int ret;
if (drv->codec_type == CODEC_PCM_DEC)
return dsp_platform_compr_lpa_pcm_copy(cstream, buf, count);
if (drv->client->input_bytes == drv->client->consume_bytes) {
if (drv->client->offset+count >= INBUF_SIZE_LPA-4096 || !buf) {
/* buf == NULL and count == 1 is for drain and */

View File

@ -288,6 +288,9 @@ u32 xf_proxy_b2a(struct xf_proxy *proxy, void *b)
else if ((u32)(b - dsp_priv->scratch_buf_virt) <
dsp_priv->scratch_buf_size)
return (u32)(b - dsp_priv->scratch_buf_virt);
else if (dsp_priv->dsp_is_lpa && ((u32)(b - dsp_priv->dram_reserved_vir_addr) <
dsp_priv->dram_reserved_size))
return (u32)(b - dsp_priv->dram_reserved_vir_addr + dsp_priv->scratch_buf_size);
else
return XF_PROXY_BADADDR;
}
@ -300,6 +303,8 @@ void *xf_proxy_a2b(struct xf_proxy *proxy, u32 address)
if (address < dsp_priv->scratch_buf_size)
return dsp_priv->scratch_buf_virt + address;
else if (dsp_priv->dsp_is_lpa && (address < dsp_priv->scratch_buf_size + dsp_priv->dram_reserved_size))
return dsp_priv->dram_reserved_vir_addr + address - dsp_priv->scratch_buf_size;
else if (address == XF_PROXY_NULL)
return NULL;
else

View File

@ -205,13 +205,18 @@ int xaf_comp_create(struct xf_client *client, struct xf_proxy *proxy,
p_comp->codec_lib.lib_type = DSP_CODEC_LIB;
}
size = INBUF_SIZE;
switch (comp_type) {
case CODEC_PCM_DEC:
p_comp->dec_id = "audio-decoder/pcm";
if (dsp_priv->dsp_is_lpa)
size = INBUF_SIZE_LPA_PCM;
break;
case CODEC_MP3_DEC:
p_comp->dec_id = "audio-decoder/mp3";
strcat(lib_path, "lib_dsp_mp3_dec.so");
if (dsp_priv->dsp_is_lpa)
size = INBUF_SIZE_LPA;
break;
case CODEC_AAC_DEC:
p_comp->dec_id = "audio-decoder/aac";
@ -258,10 +263,6 @@ int xaf_comp_create(struct xf_client *client, struct xf_proxy *proxy,
if (request_inbuf) {
/* ...allocate input buffer */
if (dsp_priv->dsp_is_lpa)
size = INBUF_SIZE_LPA;
else
size = INBUF_SIZE;
ret = xf_pool_alloc(client, proxy, 1, size,
XF_POOL_INPUT, &p_comp->inpool);
if (ret) {

View File

@ -21,6 +21,8 @@
/* ...buffer size of the buffer shared between A core and DSP. Use large */
/* ...to let A core suspend longer time to save power.*/
#define INBUF_SIZE_LPA (128*1024)
/* ...ping-pong buffer locate in DRAM for PCM LPA. */
#define INBUF_SIZE_LPA_PCM (8*1024*1024)
#define OUTBUF_SIZE 16384
struct xaf_pipeline;