.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
 
 /* stream domain */
-#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
+#define SND_SOC_DAPM_AIF_IN(wname, stname, wchan, wreg, wshift, winvert) \
 {      .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
-       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
-#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
+       .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
+#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wchan, wreg, wshift, winvert, \
                              wevent, wflags)                           \
 {      .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
-       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+       .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .event = wevent, .event_flags = wflags }
-#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
+#define SND_SOC_DAPM_AIF_OUT(wname, stname, wchan, wreg, wshift, winvert) \
 {      .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
-       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
-#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
+       .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
+#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wchan, wreg, wshift, winvert, \
                             wevent, wflags)                            \
 {      .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
-       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+       .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .event = wevent, .event_flags = wflags }
 #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
 {      .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
 int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
 void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
 
+int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai);
+
 /* dapm path setup */
 int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
 void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
        int endpoints[2];
 
        struct clk *clk;
+
+       int channel;
 };
 
 struct snd_soc_dapm_update {
 
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
 
+static int dapm_update_dai_chan(struct snd_soc_dapm_path *p,
+                               struct snd_soc_dapm_widget *w,
+                               int channels)
+{
+       switch (w->id) {
+       case snd_soc_dapm_aif_out:
+       case snd_soc_dapm_aif_in:
+               break;
+       default:
+               return 0;
+       }
+
+       dev_dbg(w->dapm->dev, "%s DAI route %s -> %s\n",
+               w->channel < channels ? "Connecting" : "Disconnecting",
+               p->source->name, p->sink->name);
+
+       if (w->channel < channels)
+               soc_dapm_connect_path(p, true, "dai update");
+       else
+               soc_dapm_connect_path(p, false, "dai update");
+
+       return 0;
+}
+
+static int dapm_update_dai_unlocked(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *params,
+                                   struct snd_soc_dai *dai)
+{
+       int dir = substream->stream;
+       int channels = params_channels(params);
+       struct snd_soc_dapm_path *p;
+       struct snd_soc_dapm_widget *w;
+       int ret;
+
+       if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+               w = dai->playback_widget;
+       else
+               w = dai->capture_widget;
+
+       dev_dbg(dai->dev, "Update DAI routes for %s %s\n", dai->name,
+               dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
+
+       snd_soc_dapm_widget_for_each_sink_path(w, p) {
+               ret = dapm_update_dai_chan(p, p->sink, channels);
+               if (ret < 0)
+                       return ret;
+       }
+
+       snd_soc_dapm_widget_for_each_source_path(w, p) {
+               ret = dapm_update_dai_chan(p, p->source, channels);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int ret;
+
+       mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+       ret = dapm_update_dai_unlocked(substream, params, dai);
+       mutex_unlock(&rtd->card->dapm_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_update_dai);
+
 /*
  * dapm_update_widget_flags() - Re-compute widget sink and source flags
  * @w: The widget for which to update the flags
                        ret = soc_dai_hw_params(&substream, params, source);
                        if (ret < 0)
                                goto out;
+
+                       dapm_update_dai_unlocked(&substream, params, source);
                }
 
                substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
                        ret = soc_dai_hw_params(&substream, params, sink);
                        if (ret < 0)
                                goto out;
+
+                       dapm_update_dai_unlocked(&substream, params, sink);
                }
                break;