summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2023-06-13 17:39:51 +0100
committerMark Brown <broonie@kernel.org>2023-06-13 17:39:51 +0100
commita11e6515b019da62266b731ff20bc6863f00df4d (patch)
tree05851998528aa12971842da8073b27678005db52
parente8181a895b05b264883288c4043ff83f893b56b0 (diff)
parent099770e2dae04579670947aaf8b5c70ef6a4cb6a (diff)
ASoC: add new trigger ordering method
Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>: This patch-set adds new "trigger" starting/stopping method.
-rw-r--r--include/sound/soc-component.h11
-rw-r--r--include/sound/soc.h23
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c20
-rw-r--r--sound/soc/amd/acp-es8336.c2
-rw-r--r--sound/soc/atmel/mchp-pdmc.c2
-rw-r--r--sound/soc/soc-pcm.c104
-rw-r--r--sound/soc/starfive/jh7110_tdm.c2
7 files changed, 93 insertions, 71 deletions
diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 0b47603c9db2..87f248a06271 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -159,6 +159,15 @@ struct snd_soc_component_driver {
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
* refcount being incremented in probe() but allow it be incremented
@@ -190,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 1e48a1135844..a7ae8b26737e 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;
@@ -713,6 +721,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;
@@ -751,12 +768,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/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,
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};
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 60cfbe565759..6fc90bc25317 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1094,49 +1094,67 @@ 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;
+ /*
+ * 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;
@@ -1150,34 +1168,20 @@ start_err:
}
}
+ /*
+ * 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;
}
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;
}