Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
[deliverable/linux.git] / sound / soc / soc-pcm.c
index 2879c883eebc2161d0c1ff3fdc14e764cde9ac33..ee15337353fae5f2cf16f5ab86f94d13440dc6bd 100644 (file)
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-static DEFINE_MUTEX(pcm_mutex);
-
-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
+                                       struct snd_soc_dai *soc_dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       if (!codec_dai->driver->symmetric_rates &&
-           !cpu_dai->driver->symmetric_rates &&
+       if (!soc_dai->driver->symmetric_rates &&
            !rtd->dai_link->symmetric_rates)
                return 0;
 
@@ -45,19 +41,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
         * the second can need to get its constraints before the first has
         * picked a rate.  Complain and allow the application to carry on.
         */
-       if (!rtd->rate) {
-               dev_warn(&rtd->dev,
+       if (!soc_dai->rate) {
+               dev_warn(soc_dai->dev,
                         "Not enforcing symmetric_rates due to race\n");
                return 0;
        }
 
-       dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+       dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
 
        ret = snd_pcm_hw_constraint_minmax(substream->runtime,
                                           SNDRV_PCM_HW_PARAM_RATE,
-                                          rtd->rate, rtd->rate);
+                                          soc_dai->rate, soc_dai->rate);
        if (ret < 0) {
-               dev_err(&rtd->dev,
+               dev_err(soc_dai->dev,
                        "Unable to apply rate symmetry constraint: %d\n", ret);
                return ret;
        }
@@ -187,8 +183,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        }
 
        /* Symmetry only applies if we've already got an active stream. */
-       if (cpu_dai->active || codec_dai->active) {
-               ret = soc_pcm_apply_symmetry(substream);
+       if (cpu_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream, cpu_dai);
+               if (ret != 0)
+                       goto config_err;
+       }
+
+       if (codec_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream, codec_dai);
                if (ret != 0)
                        goto config_err;
        }
@@ -290,8 +292,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        codec_dai->active--;
        codec->active--;
 
-       if (!cpu_dai->active && !codec_dai->active)
-               rtd->rate = 0;
+       /* clear the corresponding DAIs rate when inactive */
+       if (!cpu_dai->active)
+               cpu_dai->rate = 0;
+
+       if (!codec_dai->active)
+               codec_dai->rate = 0;
 
        /* Muting the DAC suppresses artifacts caused during digital
         * shutdown, for example from stopping clocks.
@@ -313,10 +319,17 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        cpu_dai->runtime = NULL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* start delayed pop wq here for playback streams */
-               codec_dai->pop_wait = 1;
-               schedule_delayed_work(&rtd->delayed_work,
-                       msecs_to_jiffies(rtd->pmdown_time));
+               if (unlikely(codec->ignore_pmdown_time)) {
+                       /* powered down playback stream now */
+                       snd_soc_dapm_stream_event(rtd,
+                               codec_dai->driver->playback.stream_name,
+                               SND_SOC_DAPM_STREAM_STOP);
+               } else {
+                       /* start delayed pop wq here for playback streams */
+                       codec_dai->pop_wait = 1;
+                       schedule_delayed_work(&rtd->delayed_work,
+                               msecs_to_jiffies(rtd->pmdown_time));
+               }
        } else {
                /* capture streams can be powered down now */
                snd_soc_dapm_stream_event(rtd,
@@ -449,7 +462,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       rtd->rate = params_rate(params);
+       /* store the rate for each DAIs */
+       cpu_dai->rate = params_rate(params);
+       codec_dai->rate = params_rate(params);
 
 out:
        mutex_unlock(&rtd->pcm_mutex);
This page took 0.025695 seconds and 5 git commands to generate.