diff options
author | Bing Song <bing.song@nxp.com> | 2020-06-16 13:15:29 +0800 |
---|---|---|
committer | Bing Song <bing.song@nxp.com> | 2020-07-10 16:48:11 +0800 |
commit | 23219672c1084abbf05a380b9c12230c7d270362 (patch) | |
tree | 8116aab2a1f8ad50a1b873c81d7ae0dd57061c39 /sound/soc/fsl | |
parent | 396def6370d174e5a47e11c0007896d25b03086f (diff) |
MLK-24365-4 dsp: enable dsp lpa.
One big buffer shared between A core and DSP to buffer audio
bitstram. So A core can sleep more time when DSP is playing
buffered audio bit stream.
Signed-off-by: Bing Song <bing.song@nxp.com>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r-- | sound/soc/fsl/fsl_dsp.c | 31 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_dsp.h | 4 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_dsp_platform_compress.c | 138 |
3 files changed, 148 insertions, 25 deletions
diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c index 3679191f0e66..5a7b100f9115 100644 --- a/sound/soc/fsl/fsl_dsp.c +++ b/sound/soc/fsl/fsl_dsp.c @@ -2,7 +2,7 @@ * Freescale DSP driver * * Copyright (c) 2012-2013 by Tensilica Inc. ALL RIGHTS RESERVED. - * Copyright 2018 NXP + * Copyright 2018-2020 NXP * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -795,6 +795,13 @@ static const struct file_operations dsp_fops = { .release = fsl_dsp_close, }; +extern struct snd_compr_ops dsp_platform_compr_lpa_ops; + +static const struct snd_soc_component_driver dsp_soc_platform_lpa_drv = { + .name = FSL_DSP_COMP_NAME, + .compr_ops = &dsp_platform_compr_lpa_ops, +}; + extern struct snd_compr_ops dsp_platform_compr_ops; static const struct snd_soc_component_driver dsp_soc_platform_drv = { @@ -987,6 +994,11 @@ static int fsl_dsp_probe(struct platform_device *pdev) else dsp_priv->dsp_board_type = DSP_IMX8MP_TYPE; + if (of_device_is_compatible(np, "fsl,imx8mp-dsp-lpa")) { + dsp_priv->dsp_board_type = DSP_IMX8MP_TYPE; + dsp_priv->dsp_is_lpa = 1; + } + dsp_priv->dev = &pdev->dev; /* Get the addresses and IRQ */ @@ -1126,10 +1138,18 @@ static int fsl_dsp_probe(struct platform_device *pdev) /* ...initialize mutex */ mutex_init(&dsp_priv->dsp_mutex); - ret = devm_snd_soc_register_component(&pdev->dev, &dsp_soc_platform_drv, NULL, 0); - if (ret) { - dev_err(&pdev->dev, "registering soc platform failed\n"); - goto register_component_fail; + if (dsp_priv->dsp_is_lpa) { + ret = devm_snd_soc_register_component(&pdev->dev, &dsp_soc_platform_lpa_drv, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "registering soc platform failed\n"); + goto register_component_fail; + } + } else { + ret = devm_snd_soc_register_component(&pdev->dev, &dsp_soc_platform_drv, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "registering soc platform failed\n"); + goto register_component_fail; + } } dsp_priv->esai_ipg_clk = devm_clk_get(&pdev->dev, "esai_ipg"); @@ -1504,6 +1524,7 @@ static const struct of_device_id fsl_dsp_ids[] = { { .compatible = "fsl,imx8qxp-dsp-v1", }, { .compatible = "fsl,imx8qm-dsp-v1", }, { .compatible = "fsl,imx8mp-dsp-v1", }, + { .compatible = "fsl,imx8mp-dsp-lpa", }, {} }; MODULE_DEVICE_TABLE(of, fsl_dsp_ids); diff --git a/sound/soc/fsl/fsl_dsp.h b/sound/soc/fsl/fsl_dsp.h index 9490b80e1ded..1f67b132dfba 100644 --- a/sound/soc/fsl/fsl_dsp.h +++ b/sound/soc/fsl/fsl_dsp.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT)*/ /* * Copyright (C) 2017 Cadence Design Systems, Inc. - * Copyright 2018 NXP + * Copyright 2018-2020 NXP * */ @@ -57,6 +57,7 @@ struct xf_client { int input_bytes; int consume_bytes; + int offset; }; union xf_client_link { @@ -77,6 +78,7 @@ struct fsl_dsp { struct imx_audiomix_dsp_data *audiomix; unsigned int dsp_mu_id; int dsp_mu_init; + int dsp_is_lpa; atomic_long_t refcnt; unsigned long paddr; unsigned long dram0; diff --git a/sound/soc/fsl/fsl_dsp_platform_compress.c b/sound/soc/fsl/fsl_dsp_platform_compress.c index ebc6ae60e09d..38d375e315de 100644 --- a/sound/soc/fsl/fsl_dsp_platform_compress.c +++ b/sound/soc/fsl/fsl_dsp_platform_compress.c @@ -3,7 +3,7 @@ // DSP driver compress implementation // // Copyright (c) 2012-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -// Copyright 2018 NXP +// Copyright 2018-2020 NXP #include <linux/pm_runtime.h> #include <sound/soc.h> @@ -80,11 +80,24 @@ static int dsp_platform_compr_free(struct snd_compr_stream *cstream) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component); struct dsp_data *drv = &dsp_priv->dsp_data; + struct xf_proxy *p_proxy = &dsp_priv->proxy; int ret; if (cstream->runtime->state != SNDRV_PCM_STATE_PAUSED && - cstream->runtime->state != SNDRV_PCM_STATE_RUNNING && cstream->runtime->state != SNDRV_PCM_STATE_DRAINING) { + if (dsp_priv->dsp_is_lpa) { + ret = xaf_comp_flush(drv->client, &drv->component[0]); + if (ret) { + dev_err(component->dev, "Fail to flush component, err = %d\n", ret); + return ret; + } + + ret = xaf_comp_flush(drv->client, &drv->component[1]); + if (ret) { + dev_err(component->dev, "Fail to flush component, err = %d\n", ret); + return ret; + } + } ret = xaf_comp_delete(drv->client, &drv->component[1]); if (ret) { @@ -97,6 +110,7 @@ static int dsp_platform_compr_free(struct snd_compr_stream *cstream) dev_err(component->dev, "Fail to delete component, err = %d\n", ret); return ret; } + xf_pool_free(drv->client, p_proxy->aux); } cpu_dai->driver->ops->shutdown(NULL, cpu_dai); @@ -194,6 +208,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; s_param.id = XA_RENDERER_CONFIG_PARAM_SAMPLE_RATE; s_param.mixData.value = params->codec.sample_rate; @@ -245,23 +260,25 @@ static int dsp_platform_compr_trigger_start(struct snd_compr_stream *cstream) struct xaf_comp *p_comp = &drv->component[0]; int ret; - ret = xaf_comp_process(drv->client, + if (!dsp_priv->dsp_is_lpa) { + ret = xaf_comp_process(drv->client, p_comp, p_comp->inptr, drv->client->input_bytes, XF_EMPTY_THIS_BUFFER); - ret = xaf_connect(drv->client, + 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; - } + if (ret) { + dev_err(component->dev, "Failed to connect component, err = %d\n", ret); + return ret; + } - schedule_work(&drv->client->work); + schedule_work(&drv->client->work); + } return 0; } @@ -285,17 +302,22 @@ static int dsp_platform_compr_trigger_stop(struct snd_compr_stream *cstream) dev_err(component->dev, "Fail to flush component, err = %d\n", ret); return ret; } + drv->client->input_bytes = 0; + drv->client->consume_bytes = 0; + drv->client->offset = 0; - ret = xaf_comp_delete(drv->client, &drv->component[0]); - if (ret) { - dev_err(component->dev, "Fail to delete component, err = %d\n", ret); - return ret; - } + if (!dsp_priv->dsp_is_lpa) { + ret = xaf_comp_delete(drv->client, &drv->component[0]); + if (ret) { + dev_err(component->dev, "Fail to delete component, err = %d\n", ret); + return ret; + } - ret = xaf_comp_delete(drv->client, &drv->component[1]); - if (ret) { - dev_err(component->dev, "Fail to delete component, err = %d\n", ret); - return ret; + ret = xaf_comp_delete(drv->client, &drv->component[1]); + if (ret) { + dev_err(component->dev, "Fail to delete component, err = %d\n", ret); + return ret; + } } return 0; @@ -363,7 +385,10 @@ static int dsp_platform_compr_pointer(struct snd_compr_stream *cstream, goto out; } - tstamp->copied_total = drv->client->input_bytes; + if (drv->client->input_bytes != drv->client->consume_bytes) + tstamp->copied_total = drv->client->input_bytes+drv->client->offset-4096; + else + tstamp->copied_total = drv->client->input_bytes+drv->client->offset; tstamp->byte_offset = drv->client->input_bytes; tstamp->pcm_frames = 0x900; tstamp->pcm_io_frames = g_param[1].mixData.value; @@ -414,6 +439,69 @@ static int dsp_platform_compr_copy(struct snd_compr_stream *cstream, return copied; } +static int dsp_platform_compr_lpa_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 (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 */ + /* suspend as tinycompress drain is blocking call */ + copied = count; + if (!buf) + copied = 0; + if (buf) { + ret = copy_from_user(p_comp->inptr+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->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; + } + if (!buf) + copied = count; + } else { + ret = copy_from_user(p_comp->inptr+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_get_caps(struct snd_compr_stream *cstream, struct snd_compr_caps *caps) { @@ -494,3 +582,15 @@ const struct snd_compr_ops dsp_platform_compr_ops = { .get_caps = dsp_platform_compr_get_caps, .get_codec_caps = dsp_platform_compr_get_codec_caps, }; + +const struct snd_compr_ops dsp_platform_compr_lpa_ops = { + .open = dsp_platform_compr_open, + .free = dsp_platform_compr_free, + .set_params = dsp_platform_compr_set_params, + .set_metadata = dsp_platform_compr_set_metadata, + .trigger = dsp_platform_compr_trigger, + .pointer = dsp_platform_compr_pointer, + .copy = dsp_platform_compr_lpa_copy, + .get_caps = dsp_platform_compr_get_caps, + .get_codec_caps = dsp_platform_compr_get_codec_caps, +}; |