From 356caf663deee8dc46ff3168ec0b24bcbeb00b28 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jun 2023 06:48:36 +0000 Subject: [PATCH 1/5] ASoC: add new trigger ordering method Current ASoC is assuming that trigger starting order is Link -> Component -> DAI as default, and its reverse order for stopping. But some Driver / Card want to reorder it for some reasons. We have such flags, but is unbalance like below. struct snd_soc_component_driver :: start_dma_last struct snd_soc_dai_link :: stop_dma_first We want to have more flexible, and more generic method. This patch adds new snd_soc_trigger_order for start/stop at component / DAI-link. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r0qmfnzx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 9 +++ include/sound/soc.h | 17 +++++ sound/soc/soc-pcm.c | 114 +++++++++++++++++++--------------- 3 files changed, 90 insertions(+), 50 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 0b47603c9db2..c7733382757b 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -158,6 +158,15 @@ struct snd_soc_component_driver { int probe_order; int remove_order; + /* + * soc_pcm_trigger() start/stop sequence. + * see also + * snd_soc_dai_link + * soc_pcm_trigger() + */ + enum snd_soc_trigger_order trigger_start; + enum snd_soc_trigger_order trigger_stop; + /* * signal if the module handling the component should not be removed * if a pcm is open. Setting this would prevent the module diff --git a/include/sound/soc.h b/include/sound/soc.h index 10e4ea0664af..49442583d46d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -607,6 +607,14 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +enum snd_soc_trigger_order { + /* start stop */ + SND_SOC_TRIGGER_ORDER_DEFAULT = 0, /* Link->Component->DAI DAI->Component->Link */ + SND_SOC_TRIGGER_ORDER_LDC, /* Link->DAI->Component Component->DAI->Link */ + + SND_SOC_TRIGGER_ORDER_MAX, +}; + /* SoC PCM stream information */ struct snd_soc_pcm_stream { const char *stream_name; @@ -707,6 +715,15 @@ struct snd_soc_dai_link { const struct snd_soc_ops *ops; const struct snd_soc_compr_ops *compr_ops; + /* + * soc_pcm_trigger() start/stop sequence. + * see also + * snd_soc_component_driver + * soc_pcm_trigger() + */ + enum snd_soc_trigger_order trigger_start; + enum snd_soc_trigger_order trigger_stop; + /* Mark this pcm with non atomic ops */ unsigned int nonatomic:1; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 799865a6eb56..a10c928debe3 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1071,49 +1071,77 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } +#define TRIGGER_MAX 3 +static int (* const trigger[][TRIGGER_MAX])(struct snd_pcm_substream *substream, int cmd, int rollback) = { + [SND_SOC_TRIGGER_ORDER_DEFAULT] = { + snd_soc_link_trigger, + snd_soc_pcm_component_trigger, + snd_soc_pcm_dai_trigger, + }, + [SND_SOC_TRIGGER_ORDER_LDC] = { + snd_soc_link_trigger, + snd_soc_pcm_dai_trigger, + snd_soc_pcm_component_trigger, + }, +}; + static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; - int ret = -EINVAL, _ret = 0, start_dma_last = 0, i; + int ret = 0, r = 0, i; int rollback = 0; + int start = 0, stop = 0; + /* + * select START/STOP sequence + */ + for_each_rtd_components(rtd, i, component) { + if (component->driver->trigger_start) + start = component->driver->trigger_start; + if (component->driver->trigger_stop) + stop = component->driver->trigger_stop; + } + if (rtd->dai_link->trigger_start) + start = rtd->dai_link->trigger_start; + if (rtd->dai_link->trigger_stop) + stop = rtd->dai_link->trigger_stop; + + if (start < 0 || start >= SND_SOC_TRIGGER_ORDER_MAX || + stop < 0 || stop >= SND_SOC_TRIGGER_ORDER_MAX) + return -EINVAL; + + /* REMOVE ME */ + for_each_rtd_components(rtd, i, component) { + if (component->driver->start_dma_last) { + start = SND_SOC_TRIGGER_ORDER_LDC; + break; + } + } + if (rtd->dai_link->stop_dma_first) + stop = SND_SOC_TRIGGER_ORDER_LDC; + + /* + * START + */ 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; + for (i = 0; i < TRIGGER_MAX; i++) { + r = trigger[start][i](substream, cmd, 0); + if (r < 0) break; - } } - - ret = snd_soc_link_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); - } -start_err: - if (ret < 0) - rollback = 1; } - if (rollback) { - _ret = ret; + /* + * Rollback if START failed + * find correspond STOP command + */ + if (r < 0) { + rollback = 1; + ret = r; switch (cmd) { case SNDRV_PCM_TRIGGER_START: cmd = SNDRV_PCM_TRIGGER_STOP; @@ -1127,34 +1155,20 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) } } + /* + * STOP + */ switch (cmd) { case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (rtd->dai_link->stop_dma_first) { - ret = snd_soc_pcm_component_trigger(substream, cmd, rollback); - if (ret < 0) - break; - - ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback); - if (ret < 0) - break; - } else { - ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback); - if (ret < 0) - break; - - ret = snd_soc_pcm_component_trigger(substream, cmd, rollback); - if (ret < 0) - break; + for (i = TRIGGER_MAX; i > 0; i--) { + r = trigger[stop][i - 1](substream, cmd, rollback); + if (r < 0) + ret = r; } - ret = snd_soc_link_trigger(substream, cmd, rollback); - break; } - if (_ret) - ret = _ret; - return ret; } From 4a6aeaebbe3b5ef2ae637c00840de171a6c93478 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jun 2023 06:48:51 +0000 Subject: [PATCH 2/5] ASoC: amd: use use new trigger ordering method ASoC is now supporting generic trigger ordering method. This patch switch to use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pm66fnzi.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 20 ++++++++++---------- sound/soc/amd/acp-es8336.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 375417bd7d6e..7464ca2b596c 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -524,7 +524,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { | SND_SOC_DAIFMT_CBP_CFP, .init = cz_da7219_init, .dpcm_playback = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_da7219_play_ops, SND_SOC_DAILINK_REG(designware1, dlgs, platform), }, @@ -534,7 +534,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_capture = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_da7219_cap_ops, SND_SOC_DAILINK_REG(designware2, dlgs, platform), }, @@ -544,7 +544,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_playback = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_max_play_ops, SND_SOC_DAILINK_REG(designware3, mx, platform), }, @@ -555,7 +555,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_capture = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_dmic0_cap_ops, SND_SOC_DAILINK_REG(designware3, adau, platform), }, @@ -566,7 +566,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_capture = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_dmic1_cap_ops, SND_SOC_DAILINK_REG(designware2, adau, platform), }, @@ -580,7 +580,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { | SND_SOC_DAIFMT_CBP_CFP, .init = cz_rt5682_init, .dpcm_playback = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_play_ops, SND_SOC_DAILINK_REG(designware1, rt5682, platform), }, @@ -590,7 +590,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_capture = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_cap_ops, SND_SOC_DAILINK_REG(designware2, rt5682, platform), }, @@ -600,7 +600,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_playback = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_max_play_ops, SND_SOC_DAILINK_REG(designware3, mx, platform), }, @@ -611,7 +611,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_capture = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_dmic0_cap_ops, SND_SOC_DAILINK_REG(designware3, adau, platform), }, @@ -622,7 +622,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .dpcm_capture = 1, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_dmic1_cap_ops, SND_SOC_DAILINK_REG(designware2, adau, platform), }, diff --git a/sound/soc/amd/acp-es8336.c b/sound/soc/amd/acp-es8336.c index 89499542c803..5e56d3a53be7 100644 --- a/sound/soc/amd/acp-es8336.c +++ b/sound/soc/amd/acp-es8336.c @@ -149,7 +149,7 @@ static struct snd_soc_dai_link st_dai_es8336[] = { .stream_name = "ES8336 HiFi Play", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .stop_dma_first = 1, + .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .dpcm_capture = 1, .dpcm_playback = 1, .init = st_es8336_init, From 38cb2a362d070dcabfbfb2466ca409751c426c30 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jun 2023 06:48:58 +0000 Subject: [PATCH 3/5] ASoC: atmel: use use new trigger ordering method ASoC is now supporting generic trigger ordering method. This patch switch to use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Claudiu Beznea Tested-by: Claudiu Beznea Link: https://lore.kernel.org/r/87o7lqfnzb.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index da23855a0e40..c79c73e6791e 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -423,7 +423,7 @@ static const struct snd_soc_component_driver mchp_pdmc_dai_component = { .open = &mchp_pdmc_open, .close = &mchp_pdmc_close, .legacy_dai_naming = 1, - .start_dma_last = 1, + .trigger_start = SND_SOC_TRIGGER_ORDER_LDC, }; static const unsigned int mchp_pdmc_1mic[] = {1}; From 0a67a14f74ace85cbd5bd4f49595850db2ebe53c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jun 2023 06:49:04 +0000 Subject: [PATCH 4/5] ASoC: starfive: use use new trigger ordering method ASoC is now supporting generic trigger ordering method. This patch switch to use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mt1afnz5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/starfive/jh7110_tdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/starfive/jh7110_tdm.c b/sound/soc/starfive/jh7110_tdm.c index e4bdba20c499..5f5a6ca7dbda 100644 --- a/sound/soc/starfive/jh7110_tdm.c +++ b/sound/soc/starfive/jh7110_tdm.c @@ -328,7 +328,7 @@ static int jh7110_tdm_startup(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai_link *dai_link = rtd->dai_link; - dai_link->stop_dma_first = 1; + dai_link->trigger_stop = SND_SOC_TRIGGER_ORDER_LDC; return 0; } From 099770e2dae04579670947aaf8b5c70ef6a4cb6a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jun 2023 06:49:11 +0000 Subject: [PATCH 5/5] ASoC: remove old trigger ordering method All drivers switch to use generic trigger ordering method. Let's remove old method. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87legufnyy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 -- include/sound/soc.h | 6 ------ sound/soc/soc-pcm.c | 10 ---------- 3 files changed, 18 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index c7733382757b..87f248a06271 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -199,8 +199,6 @@ 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/include/sound/soc.h b/include/sound/soc.h index 49442583d46d..52bb64d427f5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -762,12 +762,6 @@ struct snd_soc_dai_link { /* Do not create a PCM for this DAI link (Backend link) */ unsigned int ignore:1; - /* This flag will reorder stop sequence. By enabling this flag - * DMA controller stop sequence will be invoked first followed by - * CPU DAI driver stop sequence - */ - unsigned int stop_dma_first:1; - #ifdef CONFIG_SND_SOC_TOPOLOGY struct snd_soc_dobj dobj; /* For topology */ #endif diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a10c928debe3..fd45a7433c24 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1111,16 +1111,6 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) stop < 0 || stop >= SND_SOC_TRIGGER_ORDER_MAX) return -EINVAL; - /* REMOVE ME */ - for_each_rtd_components(rtd, i, component) { - if (component->driver->start_dma_last) { - start = SND_SOC_TRIGGER_ORDER_LDC; - break; - } - } - if (rtd->dai_link->stop_dma_first) - stop = SND_SOC_TRIGGER_ORDER_LDC; - /* * START */