diff --git a/sound/soc/codecs/hdac_generic.c b/sound/soc/codecs/hdac_generic.c
index f6f1658..6def114 100644
--- a/sound/soc/codecs/hdac_generic.c
+++ b/sound/soc/codecs/hdac_generic.c
@@ -708,6 +708,176 @@ static inline int hdac_generic_fill_widget_info(struct device *dev,
 	return 0;
 }
 
+static int hdac_generic_add_machine_control(struct snd_soc_dapm_context *dapm,
+				enum snd_soc_dapm_type id, const char *name,
+				struct hdac_ext_codec_widget *wid, int dir)
+{
+	struct snd_soc_dapm_widget **wid_ref;
+	struct snd_soc_dapm_widget *dapm_w;
+	struct snd_soc_dapm_route route;
+	char widget_name[HDAC_GENERIC_NAME_SIZE];
+	int ret;
+
+	dapm_w = devm_kzalloc(dapm->dev, sizeof(*dapm_w), GFP_KERNEL);
+	if (!dapm_w)
+		return -ENOMEM;
+
+	sprintf(widget_name, "%s %x", name, wid->nid);
+
+	ret = hdac_generic_fill_widget_info(dapm->dev, dapm_w,
+				id, NULL, widget_name,
+				NULL, NULL, 0, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	wid_ref = wid->priv;
+
+	snd_soc_dapm_new_control(dapm, dapm_w);
+	if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+		route.sink = dapm_w->name;
+		route.control = NULL;
+		route.source = wid_ref[0]->name;
+		route.connected = NULL;
+	} else {
+		route.sink = wid_ref[0]->name;
+		route.control = NULL;
+		route.source = dapm_w->name;
+		route.connected = NULL;
+	}
+	snd_soc_dapm_add_routes(dapm, &route, 1);
+	snd_soc_dapm_new_widgets(dapm->card);
+
+	return 0;
+}
+
+/**
+ * hdac_generic_machine_control_init - Add machine widgets and graph
+ * @dapm: machine dapm context
+ * @codec: codec object
+ *
+ * Reads the default configuration parameters and builds the machine
+ * controls and graph.
+ */
+int hdac_generic_machine_control_init(struct snd_soc_dapm_context *dapm,
+				struct snd_soc_codec *codec)
+{
+	struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
+	struct hdac_ext_codec_widget *wid;
+	struct snd_soc_dapm_widget **wid_ref;
+	unsigned int *cfg;
+	short dev;
+	int ret;
+
+	list_for_each_entry(wid, &edev->widget_list, head) {
+
+		dev_dbg(dapm->dev, "For wid: %x type: %d\n",
+				wid->nid, wid->type);
+		if (wid->type != AC_WID_PIN)
+			continue;
+
+		cfg = wid->params;
+		dev = get_defcfg_device(*cfg);
+
+		if (is_input_pin(&edev->hdac, wid->nid) &&
+				((dev == AC_JACK_LINE_OUT) ||
+				(dev == AC_JACK_SPEAKER) ||
+				(dev == AC_JACK_DIG_OTHER_OUT) ||
+				(dev == AC_JACK_HP_OUT) ||
+				(dev == AC_JACK_SPDIF_OUT))) {
+
+			dev_warn(dapm->dev,
+				"Wrong pin and dev configuration, nid: %x\n",
+				wid->nid);
+
+			continue;
+		}
+
+		switch (dev) {
+		case AC_JACK_LINE_OUT:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_line, "Lineout",
+					wid, SNDRV_PCM_STREAM_PLAYBACK);
+			if (ret < 0)
+				return ret;
+			break;
+		case AC_JACK_SPEAKER:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_spk, "spk",
+					wid, SNDRV_PCM_STREAM_PLAYBACK);
+			if (ret < 0)
+				return ret;
+			break;
+		case AC_JACK_SPDIF_OUT:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_spk, "spdif_out",
+					wid, SNDRV_PCM_STREAM_PLAYBACK);
+			if (ret < 0)
+				return ret;
+			break;
+		case AC_JACK_DIG_OTHER_OUT:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_spk, "dig_other_out",
+					wid, SNDRV_PCM_STREAM_PLAYBACK);
+			if (ret < 0)
+				return ret;
+			break;
+
+		case AC_JACK_HP_OUT:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_hp, "hp",
+					wid, SNDRV_PCM_STREAM_PLAYBACK);
+			if (ret < 0)
+				return ret;
+			break;
+
+		case AC_JACK_AUX:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_line, "Aux",
+					wid, SNDRV_PCM_STREAM_CAPTURE);
+			if (ret < 0)
+				return ret;
+			break;
+		case AC_JACK_LINE_IN:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_line, "Linein",
+					wid, SNDRV_PCM_STREAM_CAPTURE);
+			if (ret < 0)
+				return ret;
+			break;
+
+		case AC_JACK_MIC_IN:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_mic, "MIC",
+					wid, SNDRV_PCM_STREAM_CAPTURE);
+			if (ret < 0)
+				return ret;
+			break;
+		case AC_JACK_SPDIF_IN:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_mic, "spdif_in",
+					wid, SNDRV_PCM_STREAM_CAPTURE);
+			if (ret < 0)
+				return ret;
+			break;
+		case AC_JACK_DIG_OTHER_IN:
+			ret = hdac_generic_add_machine_control(dapm,
+					snd_soc_dapm_mic, "dig_other_in",
+					wid, SNDRV_PCM_STREAM_CAPTURE);
+			if (ret < 0)
+				return ret;
+			break;
+
+		default:
+			wid_ref = wid->priv;
+			snd_soc_dapm_nc_pin(dapm, wid_ref[0]->name);
+			break;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hdac_generic_machine_control_init);
+
 static int hdac_generic_alloc_mux_widget(struct snd_soc_dapm_context *dapm,
 			struct snd_soc_dapm_widget *widgets, int index,
 			struct hdac_ext_codec_widget *wid)
diff --git a/sound/soc/codecs/hdac_generic.h b/sound/soc/codecs/hdac_generic.h
index a938b50..36eafbd 100644
--- a/sound/soc/codecs/hdac_generic.h
+++ b/sound/soc/codecs/hdac_generic.h
@@ -25,4 +25,7 @@
 #define AMP_OUT_UNMUTE		0xb000
 #define PIN_OUT			(AC_PINCTL_OUT_EN)
 
+int hdac_generic_machine_control_init(struct snd_soc_dapm_context *dapm,
+					struct snd_soc_codec *codec);
+
 #endif /* __HDAC_GENERIC_H__ */
