diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 4275d7d53df..c9adaaf7116 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -120,6 +120,8 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); 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 99fe117e196..3d9f0438884 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -119,6 +119,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) /* 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 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) 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 @@ machine_err: 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 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) 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 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) 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 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) 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 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 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 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 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 2f2693de617..294e31e3ea4 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -170,7 +170,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, /* * 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 @@ static inline int be_connect(struct snd_soc_pcm_runtime *fe, { 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 @@ static int be_add_new(struct snd_soc_pcm_runtime *fe, int stream, } /* 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 @@ static int soc_dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) 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 @@ int soc_dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) /* 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 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int 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_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 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int 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_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);