summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/fsl/fsl_dsp.c3
-rw-r--r--sound/soc/fsl/fsl_dsp.h5
-rw-r--r--sound/soc/fsl/fsl_dsp_platform_compress.c78
-rw-r--r--sound/soc/fsl/fsl_dsp_proxy.c5
-rw-r--r--sound/soc/fsl/fsl_dsp_xaf_api.c9
-rw-r--r--sound/soc/fsl/fsl_dsp_xaf_api.h2
6 files changed, 97 insertions, 5 deletions
diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c
index 46c16ebc8c54..352c8dc599de 100644
--- a/sound/soc/fsl/fsl_dsp.c
+++ b/sound/soc/fsl/fsl_dsp.c
@@ -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;
diff --git a/sound/soc/fsl/fsl_dsp.h b/sound/soc/fsl/fsl_dsp.h
index a4e4537bc19e..2e2c71890819 100644
--- a/sound/soc/fsl/fsl_dsp.h
+++ b/sound/soc/fsl/fsl_dsp.h
@@ -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;
diff --git a/sound/soc/fsl/fsl_dsp_platform_compress.c b/sound/soc/fsl/fsl_dsp_platform_compress.c
index 9402b18f107c..04a33774a5f2 100644
--- a/sound/soc/fsl/fsl_dsp_platform_compress.c
+++ b/sound/soc/fsl/fsl_dsp_platform_compress.c
@@ -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 */
diff --git a/sound/soc/fsl/fsl_dsp_proxy.c b/sound/soc/fsl/fsl_dsp_proxy.c
index 84271e0a17a5..73e6e4cb6147 100644
--- a/sound/soc/fsl/fsl_dsp_proxy.c
+++ b/sound/soc/fsl/fsl_dsp_proxy.c
@@ -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
diff --git a/sound/soc/fsl/fsl_dsp_xaf_api.c b/sound/soc/fsl/fsl_dsp_xaf_api.c
index f721854ac67c..f544b6a3adba 100644
--- a/sound/soc/fsl/fsl_dsp_xaf_api.c
+++ b/sound/soc/fsl/fsl_dsp_xaf_api.c
@@ -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) {
diff --git a/sound/soc/fsl/fsl_dsp_xaf_api.h b/sound/soc/fsl/fsl_dsp_xaf_api.h
index 415aafd9fd2f..7b2dfa48977d 100644
--- a/sound/soc/fsl/fsl_dsp_xaf_api.h
+++ b/sound/soc/fsl/fsl_dsp_xaf_api.h
@@ -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;