diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 964b7de..52e89ee 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -233,6 +233,8 @@ struct snd_soc_dai_driver {
 	int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);
 	/* DAI is also used for the control bus */
 	bool bus_control;
+	/* Bind IFACE_PCM controls to the PCM device */
+	bool bind_pcm_ctl;
 
 	/* ops */
 	const struct snd_soc_dai_ops *ops;
@@ -292,6 +294,7 @@ struct snd_soc_dai {
 	unsigned int rx_mask;
 
 	struct list_head list;
+	struct list_head list_pcm_ctl;
 };
 
 static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4afa8db..148b90f 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -58,6 +58,11 @@ static LIST_HEAD(platform_list);
 static LIST_HEAD(codec_list);
 static LIST_HEAD(component_list);
 
+struct snd_soc_dai_pcm_ctls {
+	struct snd_kcontrol *controls;
+	struct list_head list;
+};
+
 /*
  * This is a timeout to do a DAPM powerdown after a stream is closed().
  * It can be used to eliminate pops between different playback streams, e.g.
@@ -1362,6 +1367,32 @@ static void soc_set_name_prefix(struct snd_soc_card *card,
 	}
 }
 
+static int soc_link_dai_pcm_controls(struct snd_soc_card *card,
+	struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai_pcm_ctls *ctls, *_ctls;
+	struct snd_kcontrol *kctl;
+	int i, err;
+
+	list_for_each_entry_safe(ctls, _ctls,  &dai->list_pcm_ctl, list) {
+		kctl = ctls->controls;
+		kctl->id.device = rtd->pcm->device;
+
+		err = snd_ctl_add(card->snd_card, kctl);
+		if (err < 0) {
+			dev_err(card->dev,
+				"ASoC: Can't link %s: %s control(s) to %s :%d\n",
+				dai->name, kctl->id.name,
+				rtd->dai_link->stream_name, err);
+			return err;
+		}
+		list_del(&ctls->list);
+		kfree(ctls);
+	}
+
+	return 0;
+}
+
 static int soc_probe_component(struct snd_soc_card *card,
 	struct snd_soc_component *component)
 {
@@ -1598,7 +1629,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
 		struct snd_soc_pcm_runtime *rtd, int order)
 {
 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *dai, *cpu_dai = rtd->cpu_dai;
 	int i, ret;
 
 	dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
@@ -1663,6 +1694,24 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
 				       dai_link->stream_name, ret);
 				return ret;
 			}
+
+			/* link  CPU DAI pcm controls to pcm device */
+			if (!list_empty(&cpu_dai->list_pcm_ctl)) {
+				ret = soc_link_dai_pcm_controls(card, cpu_dai,
+								rtd);
+				if (ret < 0)
+					return ret;
+			}
+
+			/* link CODEC DAI pcm control to pcm device */
+			for (i = 0; i < rtd->num_codecs; i++) {
+				dai = rtd->codec_dais[i];
+				if (!list_empty(&dai->list_pcm_ctl))
+					ret = soc_link_dai_pcm_controls(card,
+								      dai, rtd);
+				if (ret < 0)
+					return ret;
+			}
 		} else {
 			INIT_DELAYED_WORK(&rtd->delayed_work,
 						codec2codec_close_delayed_work);
@@ -2218,6 +2267,49 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
 	return 0;
 }
 
+static int snd_soc_add_dai_pcm_controls(struct snd_soc_card *soc_card,
+	struct snd_soc_dai *dai, const struct snd_kcontrol_new *controls,
+	int num_controls, const char *prefix, void *data)
+{
+	struct snd_soc_pcm_runtime *rtd;
+	struct snd_soc_dai_pcm_ctls *ctls_list;
+	struct snd_kcontrol *kctl;
+	int i, dai_found = 0;
+
+	for (i = 0; i < num_controls; i++) {
+		const struct snd_kcontrol_new *control = &controls[i];
+
+		if (control->iface != SNDRV_CTL_ELEM_IFACE_PCM) {
+			dev_err(dai->dev, "%s: not a pcm device control !!!\n",
+				control->name);
+			return -EINVAL;
+		}
+		kctl = snd_soc_cnew(control, data, control->name, prefix);
+		if (IS_ERR(kctl))
+			return PTR_ERR(kctl);
+
+		ctls_list = kzalloc(sizeof(*ctls_list), GFP_KERNEL);
+		ctls_list->controls = kctl;
+		list_add(&ctls_list->list, &dai->list_pcm_ctl);
+	}
+
+	if (dai->probed) {
+		/* pcm device exists. Control can be linked to it */
+		list_for_each_entry(rtd, &soc_card->rtd_list, list) {
+			if (dai == rtd->cpu_dai) {
+				dai_found = 1;
+				break;
+			}
+		}
+		if (!dai_found)
+			return -EINVAL;
+
+		soc_link_dai_pcm_controls(soc_card, dai, rtd);
+	}
+
+	return 0;
+}
+
 struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
 					       const char *name)
 {
@@ -2323,10 +2415,26 @@ EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
 int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
 	const struct snd_kcontrol_new *controls, int num_controls)
 {
-	struct snd_card *card = dai->component->card->snd_card;
+	struct snd_soc_card *soc_card = dai->component->card;
+	struct snd_card *card = soc_card->snd_card;
+	int ret, i;
 
-	return snd_soc_add_controls(card, dai->dev, controls, num_controls,
-			NULL, dai);
+	if (!dai->driver || !dai->driver->bind_pcm_ctl)
+		return snd_soc_add_controls(card, dai->dev, controls,
+			num_controls, NULL, dai);
+
+	for (i = 0; i < num_controls; i++) {
+		if (controls[i].iface == SNDRV_CTL_ELEM_IFACE_PCM)
+			ret = snd_soc_add_dai_pcm_controls(soc_card, dai,
+				&controls[i], 1, NULL, dai);
+		else
+			ret = snd_soc_add_controls(card, dai->dev, &controls[i],
+				 1, NULL, dai);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
 
@@ -2806,6 +2914,8 @@ static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component,
 	if (!dai->driver->ops)
 		dai->driver->ops = &null_dai_ops;
 
+	INIT_LIST_HEAD(&dai->list_pcm_ctl);
+
 	list_add(&dai->list, &component->dai_list);
 	component->num_dai++;
 
