ASoC: pcm: Sync delayed work before releasing resources
[sfrench/cifs-2.6.git] / sound / soc / soc-pcm.c
index 7d3859e1a7b9b9537744b53d90e74012a5454d07..c0f0b09cb433543e32bb38b7d1a17552a2f49381 100644 (file)
@@ -454,6 +454,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        const char *codec_dai_name = "multicodec";
@@ -462,10 +464,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        pinctrl_pm_select_default_state(cpu_dai->dev);
        for (i = 0; i < rtd->num_codecs; i++)
                pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev);
-       pm_runtime_get_sync(cpu_dai->dev);
-       for (i = 0; i < rtd->num_codecs; i++)
-               pm_runtime_get_sync(rtd->codec_dais[i]->dev);
-       pm_runtime_get_sync(platform->dev);
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               pm_runtime_get_sync(component->dev);
+       }
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -603,15 +607,13 @@ platform_err:
 out:
        mutex_unlock(&rtd->pcm_mutex);
 
-       pm_runtime_mark_last_busy(platform->dev);
-       pm_runtime_put_autosuspend(platform->dev);
-       for (i = 0; i < rtd->num_codecs; i++) {
-               pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
-               pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               pm_runtime_mark_last_busy(component->dev);
+               pm_runtime_put_autosuspend(component->dev);
        }
 
-       pm_runtime_mark_last_busy(cpu_dai->dev);
-       pm_runtime_put_autosuspend(cpu_dai->dev);
        for (i = 0; i < rtd->num_codecs; i++) {
                if (!rtd->codec_dais[i]->active)
                        pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
@@ -659,6 +661,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        int i;
@@ -715,17 +719,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 
        mutex_unlock(&rtd->pcm_mutex);
 
-       pm_runtime_mark_last_busy(platform->dev);
-       pm_runtime_put_autosuspend(platform->dev);
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
 
-       for (i = 0; i < rtd->num_codecs; i++) {
-               pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
-               pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
+               pm_runtime_mark_last_busy(component->dev);
+               pm_runtime_put_autosuspend(component->dev);
        }
 
-       pm_runtime_mark_last_busy(cpu_dai->dev);
-       pm_runtime_put_autosuspend(cpu_dai->dev);
-
        for (i = 0; i < rtd->num_codecs; i++) {
                if (!rtd->codec_dais[i]->active)
                        pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
@@ -2632,6 +2632,17 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
        return ret;
 }
 
+static void soc_pcm_private_free(struct snd_pcm *pcm)
+{
+       struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+       struct snd_soc_platform *platform = rtd->platform;
+
+       /* need to sync the delayed work before releasing resources */
+       flush_delayed_work(&rtd->delayed_work);
+       if (platform->driver->pcm_free)
+               platform->driver->pcm_free(pcm);
+}
+
 /* create a new pcm */
 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 {
@@ -2757,7 +2768,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
                }
        }
 
-       pcm->private_free = platform->driver->pcm_free;
+       pcm->private_free = soc_pcm_private_free;
 out:
        dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
                 (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
@@ -3000,8 +3011,7 @@ void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
                return;
        }
 
-       rtd->debugfs_dpcm_state = debugfs_create_file("state", 0444,
-                                               rtd->debugfs_dpcm_root,
-                                               rtd, &dpcm_state_fops);
+       debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
+                           rtd, &dpcm_state_fops);
 }
 #endif