/* SoC Audio Codec device */
 struct snd_soc_codec {
        const char *name;
+       const char *name_prefix;
        int id;
        struct device *dev;
        struct snd_soc_codec_driver *driver;
        struct snd_soc_ops *ops;
 };
 
+struct snd_soc_prefix_map {
+       const char *dev_name;
+       const char *name_prefix;
+};
+
 /* SoC card */
 struct snd_soc_card {
        const char *name;
        struct snd_soc_pcm_runtime *rtd;
        int num_rtd;
 
+       /*
+        * optional map of kcontrol, widget and path name prefixes that are
+        * associated per device
+        */
+       struct snd_soc_prefix_map *prefix_map;
+       int num_prefixes;
+
        struct work_struct deferred_resume_work;
 
        /* lists of probed devices belonging to this card */
 
        }
 }
 
+static void soc_set_name_prefix(struct snd_soc_card *card,
+                               struct snd_soc_codec *codec)
+{
+       int i;
+
+       if (card->prefix_map == NULL)
+               return;
+
+       for (i = 0; i < card->num_prefixes; i++) {
+               struct snd_soc_prefix_map *map = &card->prefix_map[i];
+               if (map->dev_name && !strcmp(codec->name, map->dev_name)) {
+                       codec->name_prefix = map->name_prefix;
+                       break;
+               }
+       }
+}
+
 static void rtd_release(struct device *dev) {}
 
 static int soc_probe_dai_link(struct snd_soc_card *card, int num)
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
+       const char *temp;
        int ret;
 
        dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
        /* probe the CODEC */
        if (!codec->probed) {
                codec->dapm.card = card;
+               soc_set_name_prefix(card, codec);
                if (codec->driver->probe) {
                        ret = codec->driver->probe(codec);
                        if (ret < 0) {
 
        /* now that all clients have probed, initialise the DAI link */
        if (dai_link->init) {
+               /* machine controls, routes and widgets are not prefixed */
+               temp = rtd->codec->name_prefix;
+               rtd->codec->name_prefix = NULL;
                ret = dai_link->init(rtd);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name);
                        return ret;
                }
+               rtd->codec->name_prefix = temp;
        }
 
        /* Make sure all DAPM widgets are instantiated */
        const struct snd_kcontrol_new *controls, int num_controls)
 {
        struct snd_card *card = codec->card->snd_card;
+       char prefixed_name[44], *name;
        int err, i;
 
        for (i = 0; i < num_controls; i++) {
                const struct snd_kcontrol_new *control = &controls[i];
-               err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));
+               if (codec->name_prefix) {
+                       snprintf(prefixed_name, sizeof(prefixed_name), "%s %s",
+                                codec->name_prefix, control->name);
+                       name = prefixed_name;
+               } else {
+                       name = control->name;
+               }
+               err = snd_ctl_add(card, snd_soc_cnew(control, codec, name));
                if (err < 0) {
                        dev_err(codec->dev, "%s: Failed to add %s: %d\n",
-                               codec->name, control->name, err);
+                               codec->name, name, err);
                        return err;
                }
        }
 
 
        list_for_each_entry_safe(w, next_w, &dapm->widgets, list) {
                list_del(&w->list);
+               kfree(w->name);
                kfree(w);
        }
 
 {
        struct snd_soc_dapm_path *path;
        struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
-       const char *sink = route->sink;
+       const char *sink;
        const char *control = route->control;
-       const char *source = route->source;
+       const char *source;
+       char prefixed_sink[80];
+       char prefixed_source[80];
        int ret = 0;
 
+       if (dapm->codec->name_prefix) {
+               snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
+                        dapm->codec->name_prefix, route->sink);
+               sink = prefixed_sink;
+               snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
+                        dapm->codec->name_prefix, route->source);
+               source = prefixed_source;
+       } else {
+               sink = route->sink;
+               source = route->source;
+       }
+
        /* find src and dest widgets */
        list_for_each_entry(w, &dapm->widgets, list) {
 
        const struct snd_soc_dapm_widget *widget)
 {
        struct snd_soc_dapm_widget *w;
+       size_t name_len;
 
        if ((w = dapm_cnew_widget(widget)) == NULL)
                return -ENOMEM;
 
+       name_len = strlen(widget->name) + 1;
+       if (dapm->codec->name_prefix)
+               name_len += 1 + strlen(dapm->codec->name_prefix);
+       w->name = kmalloc(name_len, GFP_KERNEL);
+       if (w->name == NULL) {
+               kfree(w);
+               return -ENOMEM;
+       }
+       if (dapm->codec->name_prefix)
+               snprintf(w->name, name_len, "%s %s",
+                       dapm->codec->name_prefix, widget->name);
+       else
+               snprintf(w->name, name_len, "%s", widget->name);
+
        w->dapm = dapm;
        w->codec = dapm->codec;
        INIT_LIST_HEAD(&w->sources);