Unverified Commit 6374f493 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: soc-pcm: care trigger rollback



soc_pcm_trigger() calls DAI/Component/Link trigger,
but some of them might be failed.

	static int soc_pcm_trigger(...)
	{
		...
		switch (cmd) {
		case SNDRV_PCM_TRIGGER_START:
		case SNDRV_PCM_TRIGGER_RESUME:
		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
			ret = snd_soc_link_trigger(substream, cmd);
			if (ret < 0)
				break;

(*)			ret = snd_soc_pcm_component_trigger(substream, cmd);
			if (ret < 0)
				break;

			ret = snd_soc_pcm_dai_trigger(substream, cmd);
			break;
		case SNDRV_PCM_TRIGGER_STOP:
		case SNDRV_PCM_TRIGGER_SUSPEND:
		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
			ret = snd_soc_pcm_dai_trigger(substream, cmd);
			if (ret < 0)
				break;

			ret = snd_soc_pcm_component_trigger(substream, cmd);
			if (ret < 0)
				break;

			ret = snd_soc_link_trigger(substream, cmd);
			break;
		}
		...
	}

For example, if soc_pcm_trigger() failed at (*) point,
we need to rollback previous succeeded trigger.

This patch adds trigger mark for DAI/Component/Link,
and do STOP if START/RESUME/PAUSE_RELEASE were failed.

Because it need to use new rollback parameter,
we need to modify DAI/Component/Link trigger functions in the same time.

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87a6uycssd.wl-kuninori.morimoto.gx@renesas.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent a9faca15
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ struct snd_soc_component {
	struct snd_pcm_substream *mark_module;
	struct snd_pcm_substream *mark_open;
	struct snd_pcm_substream *mark_hw_params;
	struct snd_pcm_substream *mark_trigger;
	struct snd_compr_stream  *mark_compr_open;
	void *mark_pm;

@@ -486,7 +487,7 @@ int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
				   int rollback);
int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
				  int cmd);
				  int cmd, int rollback);
int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
					 void *stream);
void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
+3 −1
Original line number Diff line number Diff line
@@ -189,7 +189,8 @@ int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order);
int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order);
int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd);
int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream);
int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd);
int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
			    int rollback);
int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
				    int cmd);

@@ -401,6 +402,7 @@ struct snd_soc_dai {
	/* function mark */
	struct snd_pcm_substream *mark_startup;
	struct snd_pcm_substream *mark_hw_params;
	struct snd_pcm_substream *mark_trigger;
	struct snd_compr_stream  *mark_compr_startup;

	/* bit field */
+2 −1
Original line number Diff line number Diff line
@@ -21,8 +21,9 @@ int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
			   struct snd_pcm_hw_params *params);
void snd_soc_link_hw_free(struct snd_pcm_substream *substream,
			  int rollback);
int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd);

int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd,
			 int rollback);
int snd_soc_link_compr_startup(struct snd_compr_stream *cstream);
void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream,
				 int rollback);
+1 −0
Original line number Diff line number Diff line
@@ -1042,6 +1042,7 @@ struct snd_soc_pcm_runtime {
	/* function mark */
	struct snd_pcm_substream *mark_startup;
	struct snd_pcm_substream *mark_hw_params;
	struct snd_pcm_substream *mark_trigger;
	struct snd_compr_stream  *mark_compr_startup;

	/* bit field */
+37 −8
Original line number Diff line number Diff line
@@ -1075,22 +1075,51 @@ void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
	}
}

int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
static int soc_component_trigger(struct snd_soc_component *component,
				 struct snd_pcm_substream *substream,
				 int cmd)
{
	int ret = 0;

	if (component->driver->trigger)
		ret = component->driver->trigger(component, substream, cmd);

	return soc_component_ret(component, ret);
}

int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
				  int cmd, int rollback)
{
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
	struct snd_soc_component *component;
	int i, ret;
	int i, r, ret = 0;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		for_each_rtd_components(rtd, i, component) {
		if (component->driver->trigger) {
			ret = component->driver->trigger(component, substream, cmd);
			ret = soc_component_trigger(component, substream, cmd);
			if (ret < 0)
				return soc_component_ret(component, ret);
				break;
			soc_component_mark_push(component, substream, trigger);
		}
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		for_each_rtd_components(rtd, i, component) {
			if (rollback && !soc_component_mark_match(component, substream, trigger))
				continue;

			r = soc_component_trigger(component, substream, cmd);
			if (r < 0)
				ret = r; /* use last ret */
			soc_component_mark_pop(component, substream, trigger);
		}
	}

	return 0;
	return ret;
}

int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
Loading