/* Check which widgets we need to power and store them in
         * lists indicating if they should be powered up or down.
         */
-       list_for_each_entry(w, &dapm->widgets, list) {
+       list_for_each_entry(w, &card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                switch (w->id) {
                case snd_soc_dapm_pre:
                        dapm_seq_insert(w, &down_list, dapm_down_seq);
        /* If there are no DAPM widgets then try to figure out power from the
         * event type.
         */
-       if (list_empty(&dapm->widgets)) {
+       if (!dapm->n_widgets) {
                switch (event) {
                case SND_SOC_DAPM_STREAM_START:
                case SND_SOC_DAPM_STREAM_RESUME:
        if (!dapm->debugfs_dapm)
                return;
 
-       list_for_each_entry(w, &dapm->widgets, list) {
-               if (!w->name)
+       list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (!w->name || w->dapm != dapm)
                        continue;
 
                d = debugfs_create_file(w->name, 0444,
        int count = 0;
        char *state = "not set";
 
-       list_for_each_entry(w, &codec->dapm.widgets, list) {
+       list_for_each_entry(w, &codec->card->widgets, list) {
+               if (w->dapm != &codec->dapm)
+                       continue;
 
                /* only display widgets that burnm power */
                switch (w->id) {
        struct snd_soc_dapm_widget *w, *next_w;
        struct snd_soc_dapm_path *p, *next_p;
 
-       list_for_each_entry_safe(w, next_w, &dapm->widgets, list) {
+       list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                list_del(&w->list);
                /*
                 * remove source and sink paths associated to this widget.
 {
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->widgets, list) {
+       list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                if (!strcmp(w->name, pin)) {
                        dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n",
                                pin, status);
 {
        struct snd_soc_dapm_path *path;
        struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
+       struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
        const char *sink;
        const char *control = route->control;
        const char *source;
                source = route->source;
        }
 
-       /* find src and dest widgets */
-       list_for_each_entry(w, &dapm->widgets, list) {
-
+       /*
+        * find src and dest widgets over all widgets but favor a widget from
+        * current DAPM context
+        */
+       list_for_each_entry(w, &dapm->card->widgets, list) {
                if (!wsink && !(strcmp(w->name, sink))) {
-                       wsink = w;
+                       wtsink = w;
+                       if (w->dapm == dapm)
+                               wsink = w;
                        continue;
                }
                if (!wsource && !(strcmp(w->name, source))) {
-                       wsource = w;
+                       wtsource = w;
+                       if (w->dapm == dapm)
+                               wsource = w;
                }
        }
+       /* use widget from another DAPM context if not found from this */
+       if (!wsink)
+               wsink = wtsink;
+       if (!wsource)
+               wsource = wtsource;
 
        if (wsource == NULL || wsink == NULL)
                return -ENODEV;
 {
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->widgets, list)
+       list_for_each_entry(w, &dapm->card->widgets, list)
        {
                if (w->new)
                        continue;
        else
                snprintf(w->name, name_len, "%s", widget->name);
 
+       dapm->n_widgets++;
        w->dapm = dapm;
        w->codec = dapm->codec;
        INIT_LIST_HEAD(&w->sources);
        INIT_LIST_HEAD(&w->sinks);
        INIT_LIST_HEAD(&w->list);
-       list_add(&w->list, &dapm->widgets);
+       list_add(&w->list, &dapm->card->widgets);
 
        /* machine layer set ups unconnected pins and insertions */
        w->connected = 1;
 {
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->widgets, list)
+       list_for_each_entry(w, &dapm->card->widgets, list)
        {
-               if (!w->sname)
+               if (!w->sname || w->dapm != dapm)
                        continue;
                dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
                        w->name, w->sname, stream, event);
 {
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->widgets, list) {
+       list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                if (!strcmp(w->name, pin)) {
                        dev_dbg(w->dapm->dev,
                                "dapm: force enable pin %s\n", pin);
 {
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->widgets, list) {
+       list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                if (!strcmp(w->name, pin))
                        return w->connected;
        }
 {
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->widgets, list) {
+       list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                if (!strcmp(w->name, pin)) {
                        w->ignore_suspend = 1;
                        return 0;
        LIST_HEAD(down_list);
        int powerdown = 0;
 
-       list_for_each_entry(w, &dapm->widgets, list) {
+       list_for_each_entry(w, &dapm->card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
                if (w->power) {
                        dapm_seq_insert(w, &down_list, dapm_down_seq);
                        w->power = 0;