diff mbox series

[v2,1/3] ASoC: soc-pcm: add option to start DMA after DAI

Message ID 20230217124151.236216-2-claudiu.beznea@microchip.com (mailing list archive)
State Superseded
Headers show
Series ASoC: mchp-pdmc: fix poc noises when starting capture | expand

Commit Message

Claudiu Beznea Feb. 17, 2023, 12:41 p.m. UTC
Add option to start DMA component after DAI trigger. This is done
by filling the new struct snd_soc_component_driver::start_dma_last.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 include/sound/soc-component.h |  2 ++
 sound/soc/soc-pcm.c           | 27 ++++++++++++++++++++++-----
 2 files changed, 24 insertions(+), 5 deletions(-)

Comments

Amadeusz Sławiński Feb. 17, 2023, 1:09 p.m. UTC | #1
On 2/17/2023 1:41 PM, Claudiu Beznea wrote:
> Add option to start DMA component after DAI trigger. This is done
> by filling the new struct snd_soc_component_driver::start_dma_last.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> ---
>   include/sound/soc-component.h |  2 ++
>   sound/soc/soc-pcm.c           | 27 ++++++++++++++++++++++-----
>   2 files changed, 24 insertions(+), 5 deletions(-)
> 
> diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
> index 3203d35bc8c1..0814ed143864 100644
> --- a/include/sound/soc-component.h
> +++ b/include/sound/soc-component.h
> @@ -190,6 +190,8 @@ struct snd_soc_component_driver {
>   	bool use_dai_pcm_id;	/* use DAI link PCM ID as PCM device number */
>   	int be_pcm_base;	/* base device ID for all BE PCMs */
>   
> +	unsigned int start_dma_last;
> +
>   #ifdef CONFIG_DEBUG_FS
>   	const char *debugfs_prefix;
>   #endif
> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> index 005b179a770a..5eb056b942ce 100644
> --- a/sound/soc/soc-pcm.c
> +++ b/sound/soc/soc-pcm.c
> @@ -1088,22 +1088,39 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
>   static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
>   {
>   	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
> -	int ret = -EINVAL, _ret = 0;
> +	struct snd_soc_component *component;
> +	int ret = -EINVAL, _ret = 0, start_dma_last = 0, i;
>   	int rollback = 0;
>   
>   	switch (cmd) {
>   	case SNDRV_PCM_TRIGGER_START:
>   	case SNDRV_PCM_TRIGGER_RESUME:
>   	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		/* Do we need to start dma last? */
> +		for_each_rtd_components(rtd, i, component) {
> +			if (component->driver->start_dma_last) {
> +				start_dma_last = 1;
> +				break;
> +			}
> +		}
> +
>   		ret = snd_soc_link_trigger(substream, cmd, 0);
>   		if (ret < 0)
>   			goto start_err;
>   
> -		ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
> -		if (ret < 0)
> -			goto start_err;
> +		if (start_dma_last) {
> +			ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
> +			if (ret < 0)
> +				goto start_err;
> +
> +			ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
> +		} else {
> +			ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
> +			if (ret < 0)
> +				goto start_err;
>   
> -		ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
> +			ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
> +		}
>   start_err:
>   		if (ret < 0)
>   			rollback = 1;

Can all of the above be implemented similarly to already present 
stop_dma_first? It looks similar and I don't see reason to have one flag 
in snd_soc_component_driver and other in snd_soc_dai_link.
Claudiu Beznea Feb. 17, 2023, 1:14 p.m. UTC | #2
On 17.02.2023 15:09, Amadeusz Sławiński wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On 2/17/2023 1:41 PM, Claudiu Beznea wrote:
>> Add option to start DMA component after DAI trigger. This is done
>> by filling the new struct snd_soc_component_driver::start_dma_last.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>> ---
>>   include/sound/soc-component.h |  2 ++
>>   sound/soc/soc-pcm.c           | 27 ++++++++++++++++++++++-----
>>   2 files changed, 24 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
>> index 3203d35bc8c1..0814ed143864 100644
>> --- a/include/sound/soc-component.h
>> +++ b/include/sound/soc-component.h
>> @@ -190,6 +190,8 @@ struct snd_soc_component_driver {
>>       bool use_dai_pcm_id;    /* use DAI link PCM ID as PCM device number */
>>       int be_pcm_base;        /* base device ID for all BE PCMs */
>>
>> +     unsigned int start_dma_last;
>> +
>>   #ifdef CONFIG_DEBUG_FS
>>       const char *debugfs_prefix;
>>   #endif
>> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
>> index 005b179a770a..5eb056b942ce 100644
>> --- a/sound/soc/soc-pcm.c
>> +++ b/sound/soc/soc-pcm.c
>> @@ -1088,22 +1088,39 @@ static int soc_pcm_hw_params(struct
>> snd_pcm_substream *substream,
>>   static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
>>   {
>>       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
>> -     int ret = -EINVAL, _ret = 0;
>> +     struct snd_soc_component *component;
>> +     int ret = -EINVAL, _ret = 0, start_dma_last = 0, i;
>>       int rollback = 0;
>>
>>       switch (cmd) {
>>       case SNDRV_PCM_TRIGGER_START:
>>       case SNDRV_PCM_TRIGGER_RESUME:
>>       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>> +             /* Do we need to start dma last? */
>> +             for_each_rtd_components(rtd, i, component) {
>> +                     if (component->driver->start_dma_last) {
>> +                             start_dma_last = 1;
>> +                             break;
>> +                     }
>> +             }
>> +
>>               ret = snd_soc_link_trigger(substream, cmd, 0);
>>               if (ret < 0)
>>                       goto start_err;
>>
>> -             ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
>> -             if (ret < 0)
>> -                     goto start_err;
>> +             if (start_dma_last) {
>> +                     ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
>> +                     if (ret < 0)
>> +                             goto start_err;
>> +
>> +                     ret = snd_soc_pcm_component_trigger(substream, cmd,
>> 0);
>> +             } else {
>> +                     ret = snd_soc_pcm_component_trigger(substream, cmd,
>> 0);
>> +                     if (ret < 0)
>> +                             goto start_err;
>>
>> -             ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
>> +                     ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
>> +             }
>>   start_err:
>>               if (ret < 0)
>>                       rollback = 1;
> 
> Can all of the above be implemented similarly to already present
> stop_dma_first? It looks similar and I don't see reason to have one flag
> in snd_soc_component_driver and other in snd_soc_dai_link.

That was the other solution identified; I mentioned it in v1; from v1 cover
letter/discussions:

The other solution that was identified for this was to extend the already
existing mechanism around struct snd_soc_dai_link::stop_dma_first. The downside
of this was that a potential struct snd_soc_dai_link::start_dma_last
would have to be populated on sound card driver thus, had to be taken
into account in all sound card drivers. At the moment, the mchp-pdmc is
used only with simple-audio-card. In case of simple-audio-card a new DT
binding would had to be introduced to specify this action on dai-link
descriptions (as of my investigation).

> 
>
diff mbox series

Patch

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 3203d35bc8c1..0814ed143864 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -190,6 +190,8 @@  struct snd_soc_component_driver {
 	bool use_dai_pcm_id;	/* use DAI link PCM ID as PCM device number */
 	int be_pcm_base;	/* base device ID for all BE PCMs */
 
+	unsigned int start_dma_last;
+
 #ifdef CONFIG_DEBUG_FS
 	const char *debugfs_prefix;
 #endif
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 005b179a770a..5eb056b942ce 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1088,22 +1088,39 @@  static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-	int ret = -EINVAL, _ret = 0;
+	struct snd_soc_component *component;
+	int ret = -EINVAL, _ret = 0, start_dma_last = 0, i;
 	int rollback = 0;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		/* Do we need to start dma last? */
+		for_each_rtd_components(rtd, i, component) {
+			if (component->driver->start_dma_last) {
+				start_dma_last = 1;
+				break;
+			}
+		}
+
 		ret = snd_soc_link_trigger(substream, cmd, 0);
 		if (ret < 0)
 			goto start_err;
 
-		ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
-		if (ret < 0)
-			goto start_err;
+		if (start_dma_last) {
+			ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
+			if (ret < 0)
+				goto start_err;
+
+			ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
+		} else {
+			ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
+			if (ret < 0)
+				goto start_err;
 
-		ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
+			ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
+		}
 start_err:
 		if (ret < 0)
 			rollback = 1;