From: Nicolin Chen <nicoleotsuka@gmail.com>
To: Shengjiu Wang <shengjiu.wang@nxp.com>
Cc: alsa-devel@alsa-project.org, lars@metafoo.de, timur@kernel.org,
Xiubo.Lee@gmail.com, linux-kernel@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org, lgirdwood@gmail.com,
tiwai@suse.com, broonie@kernel.org, festevam@gmail.com
Subject: Re: [RFC PATCH v2 3/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End
Date: Thu, 11 Jun 2020 17:31:04 -0700 [thread overview]
Message-ID: <20200612003103.GA28228@Asurada-Nvidia> (raw)
In-Reply-To: <0473d4191ae04ab711d63c5c875e47f45f598137.1591783089.git.shengjiu.wang@nxp.com>
On Wed, Jun 10, 2020 at 06:05:49PM +0800, Shengjiu Wang wrote:
> The dma channel has been requested by Back-End cpu dai driver already.
> If fsl_asrc_dma requests dma chan with same dma:tx symlink, then
> there will be below warning with SDMA.
>
> [ 48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink
>
> or with EDMA the request operation will fail for EDMA channel
> can only be requested once.
>
> So If we can reuse the dma channel of Back-End, then the issue can be
> fixed.
>
> In order to get the dma channel which is already requested in Back-End.
> we use the exported two functions (snd_soc_lookup_component_nolocked
> and soc_component_to_pcm). If we can get the dma channel, then reuse it,
> if can't, then request a new one.
>
> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> ---
> sound/soc/fsl/fsl_asrc_common.h | 2 ++
> sound/soc/fsl/fsl_asrc_dma.c | 52 +++++++++++++++++++++++++--------
> 2 files changed, 42 insertions(+), 12 deletions(-)
> diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
> index 77665b15c8db..09512bc79b80 100644
> --- a/sound/soc/fsl/fsl_asrc_common.h
> +++ b/sound/soc/fsl/fsl_asrc_common.h
> @@ -32,6 +32,7 @@ enum asrc_pair_index {
> * @dma_chan: inputer and output DMA channels
> * @dma_data: private dma data
> * @pos: hardware pointer position
> + * @req_dma_chan_dev_to_dev: flag for release dev_to_dev chan
Since we only have dma_request call for back-end only:
+ * @req_dma_chan: flag to release back-end dma chan
> diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
> index d6a3fc5f87e5..5ecb77d466d3 100644
> --- a/sound/soc/fsl/fsl_asrc_dma.c
> +++ b/sound/soc/fsl/fsl_asrc_dma.c
> @@ -160,6 +161,9 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> substream_be = snd_soc_dpcm_get_substream(be, stream);
> dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
> dev_be = dai->dev;
> + component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
> + if (component_be)
> + tmp_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
Should we use substream_be->stream or just substream->stream?
And would be better to add these lines right before we really use
tmp_chan because there's still some distance till it reaches that
point. And would be better to have a line of comments too.
> @@ -205,10 +209,14 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> */
> if (!asrc->use_edma) {
> /* Get DMA request of Back-End */
> - tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + if (!tmp_chan) {
> + tmp_chan_new = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + tmp_chan = tmp_chan_new;
This is a bit confusing...though I finally got it :)
So probably better to have a line of comments.
> @@ -220,9 +228,26 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
>
> pair->dma_chan[dir] =
> dma_request_channel(mask, filter, &pair->dma_data);
> + pair->req_dma_chan_dev_to_dev = true;
> } else {
> - pair->dma_chan[dir] =
> - asrc->get_dma_channel(pair, dir);
> + /*
> + * With EDMA, there is two dma channels can be used for p2p,
> + * one is from ASRC, one is from another peripheral
> + * (ESAI or SAI). Previously we select the dma channel of ASRC,
> + * but find an issue for ideal ratio case, there is no control
> + * for data copy speed, the speed is faster than sample
> + * frequency.
> + *
> + * So we switch to use dma channel of peripheral (ESAI or SAI),
> + * that copy speed of DMA is controlled by data consumption
> + * speed in the peripheral FIFO.
> + */
This sounds like a different issue and should be fixed separately?
If you prefer not to, better to move this one to commit log, other
than having a changelog here, in my opinion.
Since it no longer uses get_dma_channel() for EDMA case, we should
update the comments at the top as well.
> + pair->req_dma_chan_dev_to_dev = false;
> + pair->dma_chan[dir] = tmp_chan;
> + if (!pair->dma_chan[dir]) {
> + pair->dma_chan[dir] = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + pair->req_dma_chan_dev_to_dev = true;
> + }
> }
Now there are some duplicated lines between these if-else routines, so
combining my previous comments, we can do (sample change, not tested):
@@ -197,18 +199,29 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_CYCLIC, mask);
+ /*
+ * The Back-End device might have already requested a DMA channel,
+ * so try to reuse it first, and then request a new one upon NULL.
+ */
+ component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
+ if (component_be) // should probably error out if !component_be?
+ tmp_chan = be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
+ if (!tmp_chan)
+ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+
/*
* An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
* peripheral, unlike SDMA channel that is allocated dynamically. So no
- * need to configure dma_request and dma_request2, but get dma_chan via
- * dma_request_slave_channel directly with dma name of Front-End device
+ * need to configure dma_request and dma_request2, but get dma_chan of
+ * Back-End device directly via dma_request_slave_channel.
*/
if (!asrc->use_edma) {
/* Get DMA request of Back-End */
- tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
tmp_data = tmp_chan->private;
pair->dma_data.dma_request = tmp_data->dma_request;
- dma_release_channel(tmp_chan);
+ /* Do not release tmp_chan if we are reusing the Back-End one */
+ if (!be_chan)
+ dma_release_channel(tmp_chan);
/* Get DMA request of Front-End */
tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
pair->dma_chan[dir] =
dma_request_channel(mask, filter, &pair->dma_data);
+ pair->req_dma_chan = true;
} else {
- pair->dma_chan[dir] =
- asrc->get_dma_channel(pair, dir);
+ pair->dma_chan[dir] = tmp_chan;
+ /* Do not flag to release if we are reusing the Back-End one */
+ pair->req_dma_chan = !be_chan;
}
if (!pair->dma_chan[dir]) {
> @@ -273,19 +299,21 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
> struct snd_pcm_substream *substream)
> {
> + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
> struct snd_pcm_runtime *runtime = substream->runtime;
> struct fsl_asrc_pair *pair = runtime->private_data;
> + u8 dir = tx ? OUT : IN;
>
> snd_pcm_set_runtime_buffer(substream, NULL);
>
> - if (pair->dma_chan[IN])
> - dma_release_channel(pair->dma_chan[IN]);
> + if (pair->dma_chan[!dir])
> + dma_release_channel(pair->dma_chan[!dir]);
>
> - if (pair->dma_chan[OUT])
> - dma_release_channel(pair->dma_chan[OUT]);
> + if (pair->dma_chan[dir] && pair->req_dma_chan_dev_to_dev)
> + dma_release_channel(pair->dma_chan[dir]);
Why we only apply this to one direction?
WARNING: multiple messages have this Message-ID (diff)
From: Nicolin Chen <nicoleotsuka@gmail.com>
To: Shengjiu Wang <shengjiu.wang@nxp.com>
Cc: alsa-devel@alsa-project.org, lars@metafoo.de, timur@kernel.org,
Xiubo.Lee@gmail.com, linux-kernel@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org, lgirdwood@gmail.com,
tiwai@suse.com, broonie@kernel.org, perex@perex.cz,
festevam@gmail.com
Subject: Re: [RFC PATCH v2 3/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End
Date: Thu, 11 Jun 2020 17:31:04 -0700 [thread overview]
Message-ID: <20200612003103.GA28228@Asurada-Nvidia> (raw)
In-Reply-To: <0473d4191ae04ab711d63c5c875e47f45f598137.1591783089.git.shengjiu.wang@nxp.com>
On Wed, Jun 10, 2020 at 06:05:49PM +0800, Shengjiu Wang wrote:
> The dma channel has been requested by Back-End cpu dai driver already.
> If fsl_asrc_dma requests dma chan with same dma:tx symlink, then
> there will be below warning with SDMA.
>
> [ 48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink
>
> or with EDMA the request operation will fail for EDMA channel
> can only be requested once.
>
> So If we can reuse the dma channel of Back-End, then the issue can be
> fixed.
>
> In order to get the dma channel which is already requested in Back-End.
> we use the exported two functions (snd_soc_lookup_component_nolocked
> and soc_component_to_pcm). If we can get the dma channel, then reuse it,
> if can't, then request a new one.
>
> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> ---
> sound/soc/fsl/fsl_asrc_common.h | 2 ++
> sound/soc/fsl/fsl_asrc_dma.c | 52 +++++++++++++++++++++++++--------
> 2 files changed, 42 insertions(+), 12 deletions(-)
> diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
> index 77665b15c8db..09512bc79b80 100644
> --- a/sound/soc/fsl/fsl_asrc_common.h
> +++ b/sound/soc/fsl/fsl_asrc_common.h
> @@ -32,6 +32,7 @@ enum asrc_pair_index {
> * @dma_chan: inputer and output DMA channels
> * @dma_data: private dma data
> * @pos: hardware pointer position
> + * @req_dma_chan_dev_to_dev: flag for release dev_to_dev chan
Since we only have dma_request call for back-end only:
+ * @req_dma_chan: flag to release back-end dma chan
> diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
> index d6a3fc5f87e5..5ecb77d466d3 100644
> --- a/sound/soc/fsl/fsl_asrc_dma.c
> +++ b/sound/soc/fsl/fsl_asrc_dma.c
> @@ -160,6 +161,9 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> substream_be = snd_soc_dpcm_get_substream(be, stream);
> dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
> dev_be = dai->dev;
> + component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
> + if (component_be)
> + tmp_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
Should we use substream_be->stream or just substream->stream?
And would be better to add these lines right before we really use
tmp_chan because there's still some distance till it reaches that
point. And would be better to have a line of comments too.
> @@ -205,10 +209,14 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> */
> if (!asrc->use_edma) {
> /* Get DMA request of Back-End */
> - tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + if (!tmp_chan) {
> + tmp_chan_new = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + tmp_chan = tmp_chan_new;
This is a bit confusing...though I finally got it :)
So probably better to have a line of comments.
> @@ -220,9 +228,26 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
>
> pair->dma_chan[dir] =
> dma_request_channel(mask, filter, &pair->dma_data);
> + pair->req_dma_chan_dev_to_dev = true;
> } else {
> - pair->dma_chan[dir] =
> - asrc->get_dma_channel(pair, dir);
> + /*
> + * With EDMA, there is two dma channels can be used for p2p,
> + * one is from ASRC, one is from another peripheral
> + * (ESAI or SAI). Previously we select the dma channel of ASRC,
> + * but find an issue for ideal ratio case, there is no control
> + * for data copy speed, the speed is faster than sample
> + * frequency.
> + *
> + * So we switch to use dma channel of peripheral (ESAI or SAI),
> + * that copy speed of DMA is controlled by data consumption
> + * speed in the peripheral FIFO.
> + */
This sounds like a different issue and should be fixed separately?
If you prefer not to, better to move this one to commit log, other
than having a changelog here, in my opinion.
Since it no longer uses get_dma_channel() for EDMA case, we should
update the comments at the top as well.
> + pair->req_dma_chan_dev_to_dev = false;
> + pair->dma_chan[dir] = tmp_chan;
> + if (!pair->dma_chan[dir]) {
> + pair->dma_chan[dir] = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + pair->req_dma_chan_dev_to_dev = true;
> + }
> }
Now there are some duplicated lines between these if-else routines, so
combining my previous comments, we can do (sample change, not tested):
@@ -197,18 +199,29 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_CYCLIC, mask);
+ /*
+ * The Back-End device might have already requested a DMA channel,
+ * so try to reuse it first, and then request a new one upon NULL.
+ */
+ component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
+ if (component_be) // should probably error out if !component_be?
+ tmp_chan = be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
+ if (!tmp_chan)
+ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+
/*
* An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
* peripheral, unlike SDMA channel that is allocated dynamically. So no
- * need to configure dma_request and dma_request2, but get dma_chan via
- * dma_request_slave_channel directly with dma name of Front-End device
+ * need to configure dma_request and dma_request2, but get dma_chan of
+ * Back-End device directly via dma_request_slave_channel.
*/
if (!asrc->use_edma) {
/* Get DMA request of Back-End */
- tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
tmp_data = tmp_chan->private;
pair->dma_data.dma_request = tmp_data->dma_request;
- dma_release_channel(tmp_chan);
+ /* Do not release tmp_chan if we are reusing the Back-End one */
+ if (!be_chan)
+ dma_release_channel(tmp_chan);
/* Get DMA request of Front-End */
tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
pair->dma_chan[dir] =
dma_request_channel(mask, filter, &pair->dma_data);
+ pair->req_dma_chan = true;
} else {
- pair->dma_chan[dir] =
- asrc->get_dma_channel(pair, dir);
+ pair->dma_chan[dir] = tmp_chan;
+ /* Do not flag to release if we are reusing the Back-End one */
+ pair->req_dma_chan = !be_chan;
}
if (!pair->dma_chan[dir]) {
> @@ -273,19 +299,21 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
> struct snd_pcm_substream *substream)
> {
> + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
> struct snd_pcm_runtime *runtime = substream->runtime;
> struct fsl_asrc_pair *pair = runtime->private_data;
> + u8 dir = tx ? OUT : IN;
>
> snd_pcm_set_runtime_buffer(substream, NULL);
>
> - if (pair->dma_chan[IN])
> - dma_release_channel(pair->dma_chan[IN]);
> + if (pair->dma_chan[!dir])
> + dma_release_channel(pair->dma_chan[!dir]);
>
> - if (pair->dma_chan[OUT])
> - dma_release_channel(pair->dma_chan[OUT]);
> + if (pair->dma_chan[dir] && pair->req_dma_chan_dev_to_dev)
> + dma_release_channel(pair->dma_chan[dir]);
Why we only apply this to one direction?
WARNING: multiple messages have this Message-ID (diff)
From: Nicolin Chen <nicoleotsuka@gmail.com>
To: Shengjiu Wang <shengjiu.wang@nxp.com>
Cc: lars@metafoo.de, perex@perex.cz, tiwai@suse.com,
lgirdwood@gmail.com, broonie@kernel.org, timur@kernel.org,
Xiubo.Lee@gmail.com, festevam@gmail.com,
alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org
Subject: Re: [RFC PATCH v2 3/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End
Date: Thu, 11 Jun 2020 17:31:04 -0700 [thread overview]
Message-ID: <20200612003103.GA28228@Asurada-Nvidia> (raw)
In-Reply-To: <0473d4191ae04ab711d63c5c875e47f45f598137.1591783089.git.shengjiu.wang@nxp.com>
On Wed, Jun 10, 2020 at 06:05:49PM +0800, Shengjiu Wang wrote:
> The dma channel has been requested by Back-End cpu dai driver already.
> If fsl_asrc_dma requests dma chan with same dma:tx symlink, then
> there will be below warning with SDMA.
>
> [ 48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink
>
> or with EDMA the request operation will fail for EDMA channel
> can only be requested once.
>
> So If we can reuse the dma channel of Back-End, then the issue can be
> fixed.
>
> In order to get the dma channel which is already requested in Back-End.
> we use the exported two functions (snd_soc_lookup_component_nolocked
> and soc_component_to_pcm). If we can get the dma channel, then reuse it,
> if can't, then request a new one.
>
> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> ---
> sound/soc/fsl/fsl_asrc_common.h | 2 ++
> sound/soc/fsl/fsl_asrc_dma.c | 52 +++++++++++++++++++++++++--------
> 2 files changed, 42 insertions(+), 12 deletions(-)
> diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
> index 77665b15c8db..09512bc79b80 100644
> --- a/sound/soc/fsl/fsl_asrc_common.h
> +++ b/sound/soc/fsl/fsl_asrc_common.h
> @@ -32,6 +32,7 @@ enum asrc_pair_index {
> * @dma_chan: inputer and output DMA channels
> * @dma_data: private dma data
> * @pos: hardware pointer position
> + * @req_dma_chan_dev_to_dev: flag for release dev_to_dev chan
Since we only have dma_request call for back-end only:
+ * @req_dma_chan: flag to release back-end dma chan
> diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
> index d6a3fc5f87e5..5ecb77d466d3 100644
> --- a/sound/soc/fsl/fsl_asrc_dma.c
> +++ b/sound/soc/fsl/fsl_asrc_dma.c
> @@ -160,6 +161,9 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> substream_be = snd_soc_dpcm_get_substream(be, stream);
> dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
> dev_be = dai->dev;
> + component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
> + if (component_be)
> + tmp_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
Should we use substream_be->stream or just substream->stream?
And would be better to add these lines right before we really use
tmp_chan because there's still some distance till it reaches that
point. And would be better to have a line of comments too.
> @@ -205,10 +209,14 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> */
> if (!asrc->use_edma) {
> /* Get DMA request of Back-End */
> - tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + if (!tmp_chan) {
> + tmp_chan_new = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + tmp_chan = tmp_chan_new;
This is a bit confusing...though I finally got it :)
So probably better to have a line of comments.
> @@ -220,9 +228,26 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
>
> pair->dma_chan[dir] =
> dma_request_channel(mask, filter, &pair->dma_data);
> + pair->req_dma_chan_dev_to_dev = true;
> } else {
> - pair->dma_chan[dir] =
> - asrc->get_dma_channel(pair, dir);
> + /*
> + * With EDMA, there is two dma channels can be used for p2p,
> + * one is from ASRC, one is from another peripheral
> + * (ESAI or SAI). Previously we select the dma channel of ASRC,
> + * but find an issue for ideal ratio case, there is no control
> + * for data copy speed, the speed is faster than sample
> + * frequency.
> + *
> + * So we switch to use dma channel of peripheral (ESAI or SAI),
> + * that copy speed of DMA is controlled by data consumption
> + * speed in the peripheral FIFO.
> + */
This sounds like a different issue and should be fixed separately?
If you prefer not to, better to move this one to commit log, other
than having a changelog here, in my opinion.
Since it no longer uses get_dma_channel() for EDMA case, we should
update the comments at the top as well.
> + pair->req_dma_chan_dev_to_dev = false;
> + pair->dma_chan[dir] = tmp_chan;
> + if (!pair->dma_chan[dir]) {
> + pair->dma_chan[dir] = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
> + pair->req_dma_chan_dev_to_dev = true;
> + }
> }
Now there are some duplicated lines between these if-else routines, so
combining my previous comments, we can do (sample change, not tested):
@@ -197,18 +199,29 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_CYCLIC, mask);
+ /*
+ * The Back-End device might have already requested a DMA channel,
+ * so try to reuse it first, and then request a new one upon NULL.
+ */
+ component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
+ if (component_be) // should probably error out if !component_be?
+ tmp_chan = be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
+ if (!tmp_chan)
+ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+
/*
* An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
* peripheral, unlike SDMA channel that is allocated dynamically. So no
- * need to configure dma_request and dma_request2, but get dma_chan via
- * dma_request_slave_channel directly with dma name of Front-End device
+ * need to configure dma_request and dma_request2, but get dma_chan of
+ * Back-End device directly via dma_request_slave_channel.
*/
if (!asrc->use_edma) {
/* Get DMA request of Back-End */
- tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
tmp_data = tmp_chan->private;
pair->dma_data.dma_request = tmp_data->dma_request;
- dma_release_channel(tmp_chan);
+ /* Do not release tmp_chan if we are reusing the Back-End one */
+ if (!be_chan)
+ dma_release_channel(tmp_chan);
/* Get DMA request of Front-End */
tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
pair->dma_chan[dir] =
dma_request_channel(mask, filter, &pair->dma_data);
+ pair->req_dma_chan = true;
} else {
- pair->dma_chan[dir] =
- asrc->get_dma_channel(pair, dir);
+ pair->dma_chan[dir] = tmp_chan;
+ /* Do not flag to release if we are reusing the Back-End one */
+ pair->req_dma_chan = !be_chan;
}
if (!pair->dma_chan[dir]) {
> @@ -273,19 +299,21 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
> static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
> struct snd_pcm_substream *substream)
> {
> + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
> struct snd_pcm_runtime *runtime = substream->runtime;
> struct fsl_asrc_pair *pair = runtime->private_data;
> + u8 dir = tx ? OUT : IN;
>
> snd_pcm_set_runtime_buffer(substream, NULL);
>
> - if (pair->dma_chan[IN])
> - dma_release_channel(pair->dma_chan[IN]);
> + if (pair->dma_chan[!dir])
> + dma_release_channel(pair->dma_chan[!dir]);
>
> - if (pair->dma_chan[OUT])
> - dma_release_channel(pair->dma_chan[OUT]);
> + if (pair->dma_chan[dir] && pair->req_dma_chan_dev_to_dev)
> + dma_release_channel(pair->dma_chan[dir]);
Why we only apply this to one direction?
next prev parent reply other threads:[~2020-06-12 0:32 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-10 10:05 [RFC PATCH v2 0/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End Shengjiu Wang
2020-06-10 10:05 ` [RFC PATCH v2 1/3] ASoC: soc-card: export snd_soc_lookup_component_nolocked Shengjiu Wang
2020-06-10 10:05 ` [RFC PATCH v2 2/3] ASoC: dmaengine_pcm: export soc_component_to_pcm Shengjiu Wang
2020-06-10 10:05 ` [RFC PATCH v2 3/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End Shengjiu Wang
2020-06-12 0:31 ` Nicolin Chen [this message]
2020-06-12 0:31 ` Nicolin Chen
2020-06-12 0:31 ` Nicolin Chen
2020-06-12 2:17 ` Shengjiu Wang
2020-06-12 2:17 ` Shengjiu Wang
2020-06-12 5:02 ` Nicolin Chen
2020-06-12 5:02 ` Nicolin Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200612003103.GA28228@Asurada-Nvidia \
--to=nicoleotsuka@gmail.com \
--cc=Xiubo.Lee@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=festevam@gmail.com \
--cc=lars@metafoo.de \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=shengjiu.wang@nxp.com \
--cc=timur@kernel.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.