Merge remote-tracking branches 'asoc/fix/atmel', 'asoc/fix/intel', 'asoc/fix/rt5645...
[firefly-linux-kernel-4.4.55.git] / sound / soc / soc-pcm.c
index 57277dd79e112c2b59bf2ee3925bae6228bc30ac..eb87d96e2cf0a8807e34a9859918a5c672d17981 100644 (file)
@@ -654,6 +654,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
                        codec_dai->rate = 0;
        }
 
+       snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream);
+
        if (cpu_dai->driver->ops->shutdown)
                cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 
@@ -772,6 +774,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        for (i = 0; i < rtd->num_codecs; i++)
                snd_soc_dai_digital_mute(rtd->codec_dais[i], 0,
                                         substream->stream);
+       snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream);
 
 out:
        mutex_unlock(&rtd->pcm_mutex);
@@ -1664,6 +1667,10 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
                if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
                                continue;
 
+               /* do not free hw if this BE is used by other FE */
+               if (be->dpcm[stream].users > 1)
+                       continue;
+
                if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
@@ -2288,7 +2295,13 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
                        fe->dai_link->name);
 
                /* skip if FE doesn't have playback capability */
-               if (!fe->cpu_dai->driver->playback.channels_min)
+               if (!fe->cpu_dai->driver->playback.channels_min
+                   || !fe->codec_dai->driver->playback.channels_min)
+                       goto capture;
+
+               /* skip if FE isn't currently playing */
+               if (!fe->cpu_dai->playback_active
+                   || !fe->codec_dai->playback_active)
                        goto capture;
 
                paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
@@ -2318,7 +2331,13 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
                dpcm_path_put(&list);
 capture:
                /* skip if FE doesn't have capture capability */
-               if (!fe->cpu_dai->driver->capture.channels_min)
+               if (!fe->cpu_dai->driver->capture.channels_min
+                   || !fe->codec_dai->driver->capture.channels_min)
+                       continue;
+
+               /* skip if FE isn't currently capturing */
+               if (!fe->cpu_dai->capture_active
+                   || !fe->codec_dai->capture_active)
                        continue;
 
                paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);