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
parent
5ae911fd64
commit
c731ea37ee
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue