Merge "ASoC: core: Update FE dpcm state to trigger BE routing"
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index 4275d7d..c9adaaf 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -120,6 +120,8 @@
 int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
 int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
 int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
+int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
+	int dir, const char *stream, int event);
 
 static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
 {
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 99fe117..3d9f043 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -119,6 +119,8 @@
 	/* calculate valid and active FE <-> BE dpcms */
 	dpcm_process_paths(fe, stream, &list, 1);
 
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
 	ret = dpcm_be_dai_startup(fe, stream);
 	if (ret < 0) {
 		/* clean up all links */
@@ -133,6 +135,8 @@
 	dpcm_clear_pending_state(fe, stream);
 	dpcm_path_put(&list);
 
+	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 	mutex_unlock(&fe->card->mutex);
 
 	return 0;
@@ -144,6 +148,7 @@
 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
 		platform->driver->compr_ops->free(cstream);
 out:
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 	mutex_unlock(&fe->card->mutex);
 	return ret;
 }
@@ -249,6 +254,8 @@
 
 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
 	ret = dpcm_be_dai_hw_free(fe, stream);
 	if (ret < 0)
 		dev_err(fe->dev, "compressed hw_free failed %d\n", ret);
@@ -259,6 +266,18 @@
 	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
 		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dpcm_dapm_stream_event(fe, stream,
+				fe->cpu_dai->driver->playback.stream_name,
+				SND_SOC_DAPM_STREAM_STOP);
+	else
+		dpcm_dapm_stream_event(fe, stream,
+				fe->cpu_dai->driver->capture.stream_name,
+				SND_SOC_DAPM_STREAM_STOP);
+
+	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+
 	dpcm_be_disconnect(fe, stream);
 
 	fe->dpcm[stream].runtime = NULL;
@@ -326,9 +345,27 @@
 			goto out;
 	}
 
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
 	ret = dpcm_be_dai_trigger(fe, stream, cmd);
 
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
+		break;
+	}
+
 out:
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 	mutex_unlock(&fe->card->mutex);
 	return ret;
 }
@@ -416,9 +453,11 @@
 			goto out;
 	}
 
-
 	memcpy(&fe->dpcm[fe_substream->stream].hw_params, params,
 			sizeof(struct snd_pcm_hw_params));
+
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
 	ret = dpcm_be_dai_hw_params(fe, stream);
 	if (ret < 0)
 		goto out;
@@ -427,7 +466,19 @@
 	if (ret < 0)
 		goto out;
 
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dpcm_dapm_stream_event(fe, stream,
+				fe->cpu_dai->driver->playback.stream_name,
+				SND_SOC_DAPM_STREAM_START);
+	else
+		dpcm_dapm_stream_event(fe, stream,
+				fe->cpu_dai->driver->capture.stream_name,
+				SND_SOC_DAPM_STREAM_START);
+
+	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
+
 out:
+	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 	mutex_unlock(&fe->card->mutex);
 	return ret;
 }
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 2f2693d..294e31e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -170,7 +170,7 @@
 /*
  * stream event, send event to FE and all active BEs.
  */
-int soc_dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
+int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
 	int dir, const char *stream, int event)
 {
 	struct snd_soc_dpcm_params *dpcm_params;
@@ -833,7 +833,7 @@
 {
 	struct snd_soc_dpcm_params *dpcm_params;
 
-	if (!fe->dpcm[stream].runtime) {
+	if (!fe->dpcm[stream].runtime && !fe->fe_compr) {
 		dev_err(fe->dev, "%s no runtime\n", fe->dai_link->name);
 		return -ENODEV;
 	}
@@ -1063,7 +1063,7 @@
 			}
 
 			/* don't connect if FE is not running */
-			if (!fe->dpcm[stream].runtime)
+			if (!fe->dpcm[stream].runtime && !fe->fe_compr)
 				continue;
 
 			/* newly connected FE and BE */
@@ -1340,11 +1340,11 @@
 	dpcm_be_dai_shutdown(fe, substream->stream);
 	/* run the stream event for each BE */
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->playback.stream_name,
 				SND_SOC_DAPM_STREAM_STOP);
 	else
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->capture.stream_name,
 				SND_SOC_DAPM_STREAM_STOP);
 
@@ -1729,11 +1729,11 @@
 
 	/* run the stream event for each BE */
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->playback.stream_name,
 				SND_SOC_DAPM_STREAM_START);
 	else
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->capture.stream_name,
 				SND_SOC_DAPM_STREAM_START);
 
@@ -1861,11 +1861,11 @@
 
 	/* run the stream event for each BE */
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->playback.stream_name,
 				SND_SOC_DAPM_STREAM_NOP);
 	else
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->capture.stream_name,
 				SND_SOC_DAPM_STREAM_NOP);
 
@@ -1917,11 +1917,11 @@
 
 	/* run the stream event for each BE */
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->playback.stream_name,
 				SND_SOC_DAPM_STREAM_NOP);
 	else
-		soc_dpcm_dapm_stream_event(fe, stream,
+		dpcm_dapm_stream_event(fe, stream,
 				fe->cpu_dai->driver->capture.stream_name,
 				SND_SOC_DAPM_STREAM_NOP);