ASoC: soc-pcm: don't use bit-OR'ed error
[linux-2.6-microblaze.git] / sound / soc / soc-pcm.c
index 01e7bc0..8d8ed47 100644 (file)
 
 #define DPCM_MAX_BE_USERS      8
 
-/**
- * snd_soc_runtime_activate() - Increment active count for PCM runtime components
- * @rtd: ASoC PCM runtime that is activated
- * @stream: Direction of the PCM stream
- *
- * Increments the active count for all the DAIs and components attached to a PCM
- * runtime. Should typically be called when a stream is opened.
- *
- * Must be called with the rtd->card->pcm_mutex being held
- */
-void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
+static int soc_rtd_startup(struct snd_soc_pcm_runtime *rtd,
+                          struct snd_pcm_substream *substream)
+{
+       if (rtd->dai_link->ops &&
+           rtd->dai_link->ops->startup)
+               return rtd->dai_link->ops->startup(substream);
+       return 0;
+}
+
+static void soc_rtd_shutdown(struct snd_soc_pcm_runtime *rtd,
+                            struct snd_pcm_substream *substream)
+{
+       if (rtd->dai_link->ops &&
+           rtd->dai_link->ops->shutdown)
+               rtd->dai_link->ops->shutdown(substream);
+}
+
+static int soc_rtd_prepare(struct snd_soc_pcm_runtime *rtd,
+                          struct snd_pcm_substream *substream)
+{
+       if (rtd->dai_link->ops &&
+           rtd->dai_link->ops->prepare)
+               return rtd->dai_link->ops->prepare(substream);
+       return 0;
+}
+
+static int soc_rtd_hw_params(struct snd_soc_pcm_runtime *rtd,
+                            struct snd_pcm_substream *substream,
+                            struct snd_pcm_hw_params *params)
+{
+       if (rtd->dai_link->ops &&
+           rtd->dai_link->ops->hw_params)
+               return rtd->dai_link->ops->hw_params(substream, params);
+       return 0;
+}
+
+static void soc_rtd_hw_free(struct snd_soc_pcm_runtime *rtd,
+                           struct snd_pcm_substream *substream)
+{
+       if (rtd->dai_link->ops &&
+           rtd->dai_link->ops->hw_free)
+               rtd->dai_link->ops->hw_free(substream);
+}
+
+static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd,
+                          struct snd_pcm_substream *substream,
+                          int cmd)
+{
+       if (rtd->dai_link->ops &&
+           rtd->dai_link->ops->trigger)
+               return rtd->dai_link->ops->trigger(substream, cmd);
+       return 0;
+}
+
+static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
+                                  int stream, int action)
 {
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
@@ -47,23 +92,38 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
        lockdep_assert_held(&rtd->card->pcm_mutex);
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               cpu_dai->playback_active++;
+               cpu_dai->playback_active += action;
                for_each_rtd_codec_dai(rtd, i, codec_dai)
-                       codec_dai->playback_active++;
+                       codec_dai->playback_active += action;
        } else {
-               cpu_dai->capture_active++;
+               cpu_dai->capture_active += action;
                for_each_rtd_codec_dai(rtd, i, codec_dai)
-                       codec_dai->capture_active++;
+                       codec_dai->capture_active += action;
        }
 
-       cpu_dai->active++;
-       cpu_dai->component->active++;
+       cpu_dai->active += action;
+       cpu_dai->component->active += action;
        for_each_rtd_codec_dai(rtd, i, codec_dai) {
-               codec_dai->active++;
-               codec_dai->component->active++;
+               codec_dai->active += action;
+               codec_dai->component->active += action;
        }
 }
 
+/**
+ * snd_soc_runtime_activate() - Increment active count for PCM runtime components
+ * @rtd: ASoC PCM runtime that is activated
+ * @stream: Direction of the PCM stream
+ *
+ * Increments the active count for all the DAIs and components attached to a PCM
+ * runtime. Should typically be called when a stream is opened.
+ *
+ * Must be called with the rtd->card->pcm_mutex being held
+ */
+void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
+{
+       snd_soc_runtime_action(rtd, stream, 1);
+}
+
 /**
  * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components
  * @rtd: ASoC PCM runtime that is deactivated
@@ -76,28 +136,7 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
  */
 void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
 {
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai;
-       int i;
-
-       lockdep_assert_held(&rtd->card->pcm_mutex);
-
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               cpu_dai->playback_active--;
-               for_each_rtd_codec_dai(rtd, i, codec_dai)
-                       codec_dai->playback_active--;
-       } else {
-               cpu_dai->capture_active--;
-               for_each_rtd_codec_dai(rtd, i, codec_dai)
-                       codec_dai->capture_active--;
-       }
-
-       cpu_dai->active--;
-       cpu_dai->component->active--;
-       for_each_rtd_codec_dai(rtd, i, codec_dai) {
-               codec_dai->component->active--;
-               codec_dai->active--;
-       }
+       snd_soc_runtime_action(rtd, stream, -1);
 }
 
 /**
@@ -111,14 +150,14 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
  */
 bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_component *component;
        bool ignore = true;
+       int i;
 
        if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
                return true;
 
-       for_each_rtd_components(rtd, rtdcom, component)
+       for_each_rtd_components(rtd, i, component)
                ignore &= !component->driver->use_pmdown_time;
 
        return ignore;
@@ -428,11 +467,10 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream,
                                   struct snd_soc_component **last)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_component *component;
-       int ret = 0;
+       int i, ret = 0;
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                *last = component;
 
                ret = snd_soc_component_module_get_when_open(component);
@@ -459,15 +497,17 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream,
                                    struct snd_soc_component *last)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_component *component;
-       int ret = 0;
+       int i, r, ret = 0;
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                if (component == last)
                        break;
 
-               ret |= snd_soc_component_close(component, substream);
+               r = snd_soc_component_close(component, substream);
+               if (r < 0)
+                       ret = r; /* use last ret */
+
                snd_soc_component_module_put_when_close(component);
        }
 
@@ -484,19 +524,16 @@ 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_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";
        int i, ret = 0;
 
-       pinctrl_pm_select_default_state(cpu_dai->dev);
-       for_each_rtd_codec_dai(rtd, i, codec_dai)
-               pinctrl_pm_select_default_state(codec_dai->dev);
+       for_each_rtd_components(rtd, i, component)
+               pinctrl_pm_select_default_state(component->dev);
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component)
                pm_runtime_get_sync(component->dev);
-       }
 
        mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
 
@@ -527,13 +564,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                        codec_dai->rx_mask = 0;
        }
 
-       if (rtd->dai_link->ops->startup) {
-               ret = rtd->dai_link->ops->startup(substream);
-               if (ret < 0) {
-                       pr_err("ASoC: %s startup failed: %d\n",
-                              rtd->dai_link->name, ret);
-                       goto machine_err;
-               }
+       ret = soc_rtd_startup(rtd, substream);
+       if (ret < 0) {
+               pr_err("ASoC: %s startup failed: %d\n",
+                      rtd->dai_link->name, ret);
+               goto machine_err;
        }
 
        /* Dynamic PCM DAI links compat checks use dynamic capabilities */
@@ -600,8 +635,7 @@ dynamic:
        return 0;
 
 config_err:
-       if (rtd->dai_link->ops->shutdown)
-               rtd->dai_link->ops->shutdown(substream);
+       soc_rtd_shutdown(rtd, substream);
 
 machine_err:
        i = rtd->num_codecs;
@@ -617,47 +651,18 @@ component_err:
 out:
        mutex_unlock(&rtd->card->pcm_mutex);
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                pm_runtime_mark_last_busy(component->dev);
                pm_runtime_put_autosuspend(component->dev);
        }
 
-       for_each_rtd_codec_dai(rtd, i, codec_dai) {
-               if (!codec_dai->active)
-                       pinctrl_pm_select_sleep_state(codec_dai->dev);
-       }
-       if (!cpu_dai->active)
-               pinctrl_pm_select_sleep_state(cpu_dai->dev);
+       for_each_rtd_components(rtd, i, component)
+               if (!component->active)
+                       pinctrl_pm_select_sleep_state(component->dev);
 
        return ret;
 }
 
-/*
- * Power down the audio subsystem pmdown_time msecs after close is called.
- * This is to ensure there are no pops or clicks in between any music tracks
- * due to DAPM power cycling.
- */
-static void close_delayed_work(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
-
-       mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
-
-       dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
-                codec_dai->driver->playback.stream_name,
-                codec_dai->playback_active ? "active" : "inactive",
-                rtd->pop_wait ? "yes" : "no");
-
-       /* are we waiting on this codec DAI stream */
-       if (rtd->pop_wait == 1) {
-               rtd->pop_wait = 0;
-               snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
-                                         SND_SOC_DAPM_STREAM_STOP);
-       }
-
-       mutex_unlock(&rtd->card->pcm_mutex);
-}
-
 static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
 {
        /*
@@ -677,7 +682,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        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;
@@ -686,15 +690,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 
        snd_soc_runtime_deactivate(rtd, substream->stream);
 
-       /* clear the corresponding DAIs rate when inactive */
-       if (!cpu_dai->active)
-               cpu_dai->rate = 0;
-
-       for_each_rtd_codec_dai(rtd, i, codec_dai) {
-               if (!codec_dai->active)
-                       codec_dai->rate = 0;
-       }
-
        snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream);
 
        snd_soc_dai_shutdown(cpu_dai, substream);
@@ -702,43 +697,22 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        for_each_rtd_codec_dai(rtd, i, codec_dai)
                snd_soc_dai_shutdown(codec_dai, substream);
 
-       if (rtd->dai_link->ops->shutdown)
-               rtd->dai_link->ops->shutdown(substream);
+       soc_rtd_shutdown(rtd, substream);
 
        soc_pcm_components_close(substream, NULL);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
-                       /* powered down playback stream now */
-                       snd_soc_dapm_stream_event(rtd,
-                                                 SNDRV_PCM_STREAM_PLAYBACK,
-                                                 SND_SOC_DAPM_STREAM_STOP);
-               } else {
-                       /* start delayed pop wq here for playback streams */
-                       rtd->pop_wait = 1;
-                       queue_delayed_work(system_power_efficient_wq,
-                                          &rtd->delayed_work,
-                                          msecs_to_jiffies(rtd->pmdown_time));
-               }
-       } else {
-               /* capture streams can be powered down now */
-               snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
-                                         SND_SOC_DAPM_STREAM_STOP);
-       }
+       snd_soc_dapm_stream_stop(rtd, substream->stream);
 
        mutex_unlock(&rtd->card->pcm_mutex);
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                pm_runtime_mark_last_busy(component->dev);
                pm_runtime_put_autosuspend(component->dev);
        }
 
-       for_each_rtd_codec_dai(rtd, i, codec_dai) {
-               if (!codec_dai->active)
-                       pinctrl_pm_select_sleep_state(codec_dai->dev);
-       }
-       if (!cpu_dai->active)
-               pinctrl_pm_select_sleep_state(cpu_dai->dev);
+       for_each_rtd_components(rtd, i, component)
+               if (!component->active)
+                       pinctrl_pm_select_sleep_state(component->dev);
 
        return 0;
 }
@@ -752,23 +726,20 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        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, ret = 0;
 
        mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
 
-       if (rtd->dai_link->ops->prepare) {
-               ret = rtd->dai_link->ops->prepare(substream);
-               if (ret < 0) {
-                       dev_err(rtd->card->dev, "ASoC: machine prepare error:"
-                               " %d\n", ret);
-                       goto out;
-               }
+       ret = soc_rtd_prepare(rtd, substream);
+       if (ret < 0) {
+               dev_err(rtd->card->dev,
+                       "ASoC: machine prepare error: %d\n", ret);
+               goto out;
        }
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                ret = snd_soc_component_prepare(component, substream);
                if (ret < 0) {
                        dev_err(component->dev,
@@ -829,15 +800,16 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream,
                                      struct snd_soc_component *last)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_component *component;
-       int ret = 0;
+       int i, r, ret = 0;
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                if (component == last)
                        break;
 
-               ret |= snd_soc_component_hw_free(component, substream);
+               r = snd_soc_component_hw_free(component, substream);
+               if (r < 0)
+                       ret = r; /* use last ret */
        }
 
        return ret;
@@ -853,7 +825,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        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, ret = 0;
@@ -864,13 +835,11 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ret)
                goto out;
 
-       if (rtd->dai_link->ops->hw_params) {
-               ret = rtd->dai_link->ops->hw_params(substream, params);
-               if (ret < 0) {
-                       dev_err(rtd->card->dev, "ASoC: machine hw_params"
-                               " failed: %d\n", ret);
-                       goto out;
-               }
+       ret = soc_rtd_hw_params(rtd, substream, params);
+       if (ret < 0) {
+               dev_err(rtd->card->dev,
+                       "ASoC: machine hw_params failed: %d\n", ret);
+               goto out;
        }
 
        for_each_rtd_codec_dai(rtd, i, codec_dai) {
@@ -932,7 +901,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 
        snd_soc_dapm_update_dai(substream, params, cpu_dai);
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                ret = snd_soc_component_hw_params(component, substream, params);
                if (ret < 0) {
                        dev_err(component->dev,
@@ -965,8 +934,7 @@ codec_err:
                codec_dai->rate = 0;
        }
 
-       if (rtd->dai_link->ops->hw_free)
-               rtd->dai_link->ops->hw_free(substream);
+       soc_rtd_hw_free(rtd, substream);
 
        mutex_unlock(&rtd->card->pcm_mutex);
        return ret;
@@ -1009,8 +977,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        }
 
        /* free any machine hw params */
-       if (rtd->dai_link->ops->hw_free)
-               rtd->dai_link->ops->hw_free(substream);
+       soc_rtd_hw_free(rtd, substream);
 
        /* free any component resources */
        soc_pcm_components_hw_free(substream, NULL);
@@ -1033,18 +1000,15 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        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, ret;
 
-       if (rtd->dai_link->ops->trigger) {
-               ret = rtd->dai_link->ops->trigger(substream, cmd);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = soc_rtd_trigger(rtd, substream, cmd);
+       if (ret < 0)
+               return ret;
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                ret = snd_soc_component_trigger(component, substream, cmd);
                if (ret < 0)
                        return ret;
@@ -1067,7 +1031,6 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        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, ret;
@@ -1082,17 +1045,15 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd)
        if (ret < 0)
                return ret;
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                ret = snd_soc_component_trigger(component, substream, cmd);
                if (ret < 0)
                        return ret;
        }
 
-       if (rtd->dai_link->ops->trigger) {
-               ret = rtd->dai_link->ops->trigger(substream, cmd);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = soc_rtd_trigger(rtd, substream, cmd);
+       if (ret < 0)
+               return ret;
 
        return 0;
 }
@@ -1350,12 +1311,12 @@ static inline struct snd_soc_dapm_widget *
 static int widget_in_list(struct snd_soc_dapm_widget_list *list,
                struct snd_soc_dapm_widget *widget)
 {
+       struct snd_soc_dapm_widget *w;
        int i;
 
-       for (i = 0; i < list->num_widgets; i++) {
-               if (widget == list->widgets[i])
+       for_each_dapm_widgets(list, i, w)
+               if (widget == w)
                        return 1;
-       }
 
        return 0;
 }
@@ -1466,12 +1427,13 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
        struct snd_soc_card *card = fe->card;
        struct snd_soc_dapm_widget_list *list = *list_;
        struct snd_soc_pcm_runtime *be;
+       struct snd_soc_dapm_widget *widget;
        int i, new = 0, err;
 
        /* Create any new FE <--> BE connections */
-       for (i = 0; i < list->num_widgets; i++) {
+       for_each_dapm_widgets(list, i, widget) {
 
-               switch (list->widgets[i]->id) {
+               switch (widget->id) {
                case snd_soc_dapm_dai_in:
                        if (stream != SNDRV_PCM_STREAM_PLAYBACK)
                                continue;
@@ -1485,10 +1447,10 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
                }
 
                /* is there a valid BE rtd for this widget */
-               be = dpcm_get_be(card, list->widgets[i], stream);
+               be = dpcm_get_be(card, widget, stream);
                if (!be) {
                        dev_err(fe->dev, "ASoC: no BE found for %s\n",
-                                       list->widgets[i]->name);
+                                       widget->name);
                        continue;
                }
 
@@ -1504,7 +1466,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
                err = dpcm_be_connect(fe, be, stream);
                if (err < 0) {
                        dev_err(fe->dev, "ASoC: can't connect %s\n",
-                               list->widgets[i]->name);
+                               widget->name);
                        break;
                } else if (err == 0) /* already connected */
                        continue;
@@ -2026,7 +1988,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
        soc_pcm_close(substream);
 
        /* run the stream event for each BE */
-       dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
+       snd_soc_dapm_stream_stop(fe, stream);
 
        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
        dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
@@ -2897,7 +2859,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 {
        struct snd_soc_dai *codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_component *component;
        struct snd_pcm *pcm;
        char new_name[64];
@@ -2916,10 +2877,10 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
                for_each_rtd_codec_dai(rtd, i, codec_dai) {
                        if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
-                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
+                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
                                playback = 1;
                        if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
-                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
+                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
                                capture = 1;
                }
 
@@ -2974,7 +2935,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
        if (rtd->dai_link->params)
                rtd->close_delayed_work_func = codec2codec_close_delayed_work;
        else
-               rtd->close_delayed_work_func = close_delayed_work;
+               rtd->close_delayed_work_func = snd_soc_close_delayed_work;
 
        pcm->nonatomic = rtd->dai_link->nonatomic;
        rtd->pcm = pcm;
@@ -3007,7 +2968,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
                rtd->ops.pointer        = soc_pcm_pointer;
        }
 
-       for_each_rtd_components(rtd, rtdcom, component) {
+       for_each_rtd_components(rtd, i, component) {
                const struct snd_soc_component_driver *drv = component->driver;
 
                if (drv->ioctl)