diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 618af31..bfa0ffb 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -88,6 +88,7 @@ struct hdac_hdmi_pin {
 };
 
 struct hdac_hdmi_port {
+	struct list_head head;
 	int id;
 	struct hdac_hdmi_pin *pin;
 	int num_mux_nids;
@@ -96,15 +97,17 @@ struct hdac_hdmi_port {
 	bool chmap_set;
 	unsigned char chmap[8]; /* ALSA API channel-map */
 	int channels; /* current number of channels */
+	bool is_connected; /* flag to indicate device connected to port */
 };
 
 struct hdac_hdmi_pcm {
 	struct list_head head;
 	struct mutex lock;
 	int pcm_id;
-	struct hdac_hdmi_port *port;
+	struct list_head port_list;
 	struct hdac_hdmi_cvt *cvt;
 	struct snd_jack *jack;
+	int jack_event;
 };
 
 struct hdac_hdmi_dai_port_map {
@@ -125,6 +128,39 @@ struct hdac_hdmi_priv {
 	struct hdac_chmap chmap;
 };
 
+static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
+		struct hdac_hdmi_port *port, bool is_connect)
+{
+	struct hdac_ext_device *edev = port->pin->edev;
+
+	if (is_connect) {
+		/*
+		 * Report Jack connect event when a device is connected
+		 * for the first time where same PCM is attached to mutiple
+		 * ports.
+		 */
+		if (pcm->jack_event == 0) {
+			dev_dbg(&edev->hdac.dev,
+					"jack report for pcm=%d\n",
+					pcm->pcm_id);
+			snd_jack_report(pcm->jack, SND_JACK_AVOUT);
+		}
+		pcm->jack_event++;
+		port->is_connected = true;
+	} else {
+		/*
+		 * Report Jack disconnect event when a device is disconnected
+		 * is the only last connected device when same PCM is attached
+		 * to mutiple ports.
+		 */
+		if (pcm->jack_event == 1)
+			snd_jack_report(pcm->jack, 0);
+		if (pcm->jack_event > 0)
+			pcm->jack_event--;
+		port->is_connected = false;
+	}
+}
+
 static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm_from_cvt(
 			struct hdac_hdmi_priv *hdmi,
 			struct hdac_hdmi_cvt *cvt)
@@ -212,7 +248,7 @@ static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev,
 		                struct hdac_hdmi_dai_port_map *dai_map);
 
 static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac,
-		                struct hdac_hdmi_dai_port_map *dai_map);
+                struct hdac_hdmi_port *port, struct hdac_hdmi_cvt *cvt);
 
 static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
 						int pcm_idx)
@@ -274,13 +310,12 @@ format_constraint:
 }
 
 static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
-				hda_nid_t cvt_nid, hda_nid_t pin_nid,
-				u32 stream_tag, int format)
+		 hda_nid_t cvt_nid, u32 stream_tag, int format)
 {
 	unsigned int val;
 
-	dev_dbg(&hdac->hdac.dev, "cvt nid %d pnid %d stream %d format 0x%x\n",
-			cvt_nid, pin_nid, stream_tag, format);
+	dev_dbg(&hdac->hdac.dev, "cvt nid %d stream %d format 0x%x\n",
+			cvt_nid, stream_tag, format);
 
 	val = (stream_tag << 4);
 
@@ -409,9 +444,10 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
 }
 
 static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
-		struct hdac_hdmi_dai_port_map *dai_map, unsigned int pwr_state)
+	    struct hdac_hdmi_cvt *cvt, struct hdac_hdmi_port *port,
+	    unsigned int pwr_state)
 {
-	struct hdac_hdmi_pin *pin = dai_map->port->pin;
+	struct hdac_hdmi_pin *pin = port->pin;
 
 	/* Power up pin widget */
 	if (!snd_hdac_check_power_state(&edev->hdac, pin->nid,
@@ -420,9 +456,9 @@ static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
 			AC_VERB_SET_POWER_STATE, pwr_state);
 
 	/* Power up converter */
-	if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt->nid,
+	if (!snd_hdac_check_power_state(&edev->hdac, cvt->nid,
 						pwr_state))
-		snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
+		snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
 			AC_VERB_SET_POWER_STATE, pwr_state);
 }
 
@@ -438,7 +474,6 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
 	int ret;
 
 	dai_map = &hdmi->dai_map[dai->id];
-	port = dai_map->port;
 
 	dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
 	dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n",
@@ -450,21 +485,30 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
 	if (!pcm)
 		return -EIO;
 
-	mutex_lock(&pcm->lock);
-	ret = hdac_hdmi_enable_pin(hdac, dai_map);
-	if (ret < 0)
-		return ret;
+	if (list_empty(&pcm->port_list))
+		return -EIO;
 
-	port->channels = substream->runtime->channels;
+	mutex_lock(&pcm->lock);
+	list_for_each_entry(port, &pcm->port_list, head) {
+		if (port->is_connected) {
+			ret = hdac_hdmi_enable_pin(hdac, port, dai_map->cvt);
+			if (ret < 0) {
+				mutex_unlock(&pcm->lock);
+				return ret;
+			}
+			port->channels = substream->runtime->channels;
 
-	ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
+			ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
 						port->pin->nid, port);
+			if (ret < 0) {
+				mutex_unlock(&pcm->lock);
+				return ret;
+			}
+		}
+	}
 	mutex_unlock(&pcm->lock);
-	if (ret < 0)
-		return ret;
 
-	return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid,
-			port->pin->nid, dd->stream_tag, dd->format);
+	return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid, dd->stream_tag, dd->format);
 }
 
 static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
@@ -538,17 +582,16 @@ static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev,
 }
 
 static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac,
-		struct hdac_hdmi_dai_port_map *dai_map)
+	struct hdac_hdmi_port *port, struct hdac_hdmi_cvt *cvt)
 {
 	int mux_idx;
-	struct hdac_hdmi_port *port = dai_map->port;
 
 	/* set the device if pin is mst_capable */
 	if (hdac_hdmi_port_select_set(hdac, port) < 0)
 		return -EIO;
 
 	for (mux_idx = 0; mux_idx < port->num_mux_nids; mux_idx++) {
-		if (port->mux_nids[mux_idx] == dai_map->cvt->nid) {
+		if (port->mux_nids[mux_idx] == cvt->nid) {
 			snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
 					AC_VERB_SET_CONNECT_SEL, mux_idx);
 			break;
@@ -562,7 +605,7 @@ static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac,
 	snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
 			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 
-	hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0);
+	hdac_hdmi_set_power_state(hdac, cvt, port, AC_PWRST_D0);
 
 	snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
 			AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
@@ -614,30 +657,33 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
 			struct hdac_hdmi_cvt *cvt)
 {
 	struct hdac_hdmi_pcm *pcm;
-	struct hdac_hdmi_port *port = NULL;
+	struct hdac_hdmi_port *port = NULL, *valid_port = NULL;
 	int ret, i;
 
 	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
 		if (pcm->cvt == cvt) {
-			port = pcm->port;
-			break;
-		}
-	}
+			if (list_empty(&pcm->port_list))
+				continue;
 
-	if (port) {
-		mutex_lock(&pcm->lock);
-		ret = hdac_hdmi_query_port_connlist(edev, port->pin, port);
-		mutex_unlock(&pcm->lock);
+			list_for_each_entry(port, &pcm->port_list, head) {
+				mutex_lock(&pcm->lock);
+				ret = hdac_hdmi_query_port_connlist(edev, port->pin, port);
+				mutex_unlock(&pcm->lock);
 
-		if (ret < 0)
-			return NULL;
+				if (ret < 0)
+					return NULL;
 
-		for (i = 0; i < port->num_mux_nids; i++) {
-			if (port->mux_nids[i] == cvt->nid)
-				return port;
+				for (i = 0; i < port->num_mux_nids; i++) {
+					if (port->mux_nids[i] == cvt->nid)
+						valid_port = port;
+				}
+			}
 		}
 	}
 
+	if (valid_port)
+		return valid_port;
+
 	return NULL;
 }
 
@@ -667,7 +713,6 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
 	 */
 	if (!port)
 		return 0;
-
 	if ((!port->eld.monitor_present) ||
 			(!port->eld.eld_valid)) {
 
@@ -693,19 +738,10 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
 static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
 		struct snd_soc_dai *dai)
 {
-	struct hdac_hdmi_dai_port_map *dai_map;
-	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
-	struct hdac_hdmi_priv *hdmi = hdac->private_data;
-	int ret;
-
-	dai_map = &hdmi->dai_map[dai->id];
-	if (cmd == SNDRV_PCM_TRIGGER_RESUME) {
-		ret = hdac_hdmi_enable_pin(hdac, dai_map);
-		if (ret < 0)
-			return ret;
 
+	if (cmd == SNDRV_PCM_TRIGGER_RESUME)
 		return hdac_hdmi_playback_prepare(substream, dai);
-	}
+
 
 	return 0;
 }
@@ -718,32 +754,39 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
 	struct hdac_hdmi_dai_port_map *dai_map;
 	struct hdac_hdmi_port *port;
 	struct hdac_hdmi_pcm *pcm;
+	struct hdac_hdmi_cvt *cvt;
 
 	dai_map = &hdmi->dai_map[dai->id];
 
 	pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
 
+	cvt = dai_map->cvt;
+
 	if (dai_map->port && pcm) {
-		port = dai_map->port;
 		snd_hdac_codec_write(&hdac->hdac, dai_map->cvt->nid, 0,
 				AC_VERB_SET_CHANNEL_STREAMID, 0);
 		snd_hdac_codec_write(&hdac->hdac, dai_map->cvt->nid, 0,
 				AC_VERB_SET_STREAM_FORMAT, 0);
 
-		mutex_lock(&pcm->lock);
-		/* set the device if pin is mst_capable */
-		if (!hdac_hdmi_port_select_set(hdac, port)) {
-			hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
+		if (!list_empty(&pcm->port_list)) {
+			mutex_lock(&pcm->lock);
+			list_for_each_entry(port, &pcm->port_list, head) {
+				/* set the device if pin is mst_capable */
+				if (!hdac_hdmi_port_select_set(hdac, port)) {
+					hdac_hdmi_set_power_state(hdac, cvt, port,
+								  AC_PWRST_D3);
 
-			snd_hdac_codec_write(&hdac->hdac, dai_map->port->pin->nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-		}
-		dai_map->port->chmap_set = false;
-		memset(dai_map->port->chmap, 0, sizeof(dai_map->port->chmap));
-		dai_map->port->channels = 0;
-		mutex_unlock(&pcm->lock);
+					snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
+						AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+				}
 
-		dai_map->port = NULL;
+				port->chmap_set = false;
+				memset(port->chmap, 0, sizeof(port->chmap));
+				port->channels = 0;
+				dai_map->port = NULL;
+			}
+			mutex_unlock(&pcm->lock);
+		}
 	}
 }
 
@@ -813,13 +856,16 @@ static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
 {
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = NULL;
+	struct hdac_hdmi_port *p;
 
 	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
-		if (!pcm->port)
+		if (list_empty(&pcm->port_list))
 			continue;
 
-		if (pcm->port == port)
-			return pcm;
+		list_for_each_entry(p, &pcm->port_list, head) {
+			if (p->id == port->id && port->pin == p->pin)
+				return pcm;
+		}
 	}
 
 	return NULL;
@@ -832,6 +878,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
 	int ret;
+	struct hdac_hdmi_port *p, *p_next;
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
 	struct snd_soc_dapm_context *dapm = w->dapm;
@@ -850,25 +897,30 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&hdmi->pin_mutex);
 	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
-		if (!pcm->port && pcm->port == port &&
-			pcm->port->id == port->id)
-			pcm->port = NULL;
+		if (list_empty(&pcm->port_list))
+			continue;
 
-		/*
-		 * Jack status is not reported during device probe as the
-		 * PCMs are not registered by then. So report it here.
-		 */
-		if (!strcmp(cvt_name, pcm->cvt->name) && !pcm->port) {
-			pcm->port = port;
-			if (port->eld.monitor_present && port->eld.eld_valid) {
-				dev_dbg(&edev->hdac.dev,
-					"jack report for pcm=%d\n",
-					pcm->pcm_id);
+		list_for_each_entry_safe(p, p_next, &pcm->port_list, head) {
+			if (p == port && p->id == port->id &&
+					p->pin == port->pin) {
+				hdac_hdmi_jack_report(pcm, port, false);
+				list_del(&p->head);
+			}
+		}
+	}
 
-				snd_jack_report(pcm->jack, SND_JACK_AVOUT);
+	/*
+	 * Jack status is not reported during device probe as the
+	 * PCMs are not registered by then. So report it here.
+	 */
+	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
+		if (!strcmp(cvt_name, pcm->cvt->name)) {
+			list_add_tail(&port->head, &pcm->port_list);
+			if (port->eld.monitor_present && port->eld.eld_valid) {
+				hdac_hdmi_jack_report(pcm, port, true);
+				mutex_unlock(&hdmi->pin_mutex);
+				return ret;
 			}
-			mutex_unlock(&hdmi->pin_mutex);
-			return ret;
 		}
 	}
 	mutex_unlock(&hdmi->pin_mutex);
@@ -1209,25 +1261,16 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
 		 * report jack here. It will be done in usermode mux
 		 * control select.
 		 */
-		if (pcm) {
-			dev_dbg(&edev->hdac.dev,
-				"jack report for pcm=%d\n", pcm->pcm_id);
-
-			snd_jack_report(pcm->jack, 0);
-		}
+		if (pcm)
+			hdac_hdmi_jack_report(pcm, port, false);
 
 		mutex_unlock(&hdmi->pin_mutex);
 		return;
 	}
 
 	if (port->eld.monitor_present && port->eld.eld_valid) {
-		if (pcm) {
-			dev_dbg(&edev->hdac.dev,
-				"jack report for pcm=%d\n",
-				pcm->pcm_id);
-
-			snd_jack_report(pcm->jack, SND_JACK_AVOUT);
-		}
+		if (pcm)
+			hdac_hdmi_jack_report(pcm, port, true);
 
 		print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
 			  port->eld.eld_buffer, port->eld.eld_size, false);
@@ -1551,8 +1594,9 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device)
 		return -ENOMEM;
 	pcm->pcm_id = device;
 	pcm->cvt = hdmi->dai_map[dai->id].cvt;
+	pcm->jack_event = 0;
 	mutex_init(&pcm->lock);
-
+	INIT_LIST_HEAD(&pcm->port_list);
 	snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device);
 	if (snd_pcm) {
 		err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap);
@@ -1610,6 +1654,11 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
+	/* FIXME
+	 * At boot driver does not know if the port is mst capable, to get
+	 * the ELD, i915 acomp API expects to pass pipe id as -1 when the
+	 * port is non mst.
+	 */
 	list_for_each_entry(pin, &hdmi->pin_list, head)
 		for (i = 0; i < pin->num_ports; i++)
 			hdac_hdmi_present_sense(pin, &pin->ports[i]);
@@ -1700,13 +1749,15 @@ static void hdac_hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
 	struct hdac_ext_device *edev = to_ehdac_device(hdac);
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
-	struct hdac_hdmi_port *port = pcm->port;
+	struct hdac_hdmi_port *port;
 
-	/* chmap is already set to 0 in caller */
-	if (!port)
+	if (list_empty(&pcm->port_list))
 		return;
 
-	memcpy(chmap, port->chmap, ARRAY_SIZE(port->chmap));
+	list_for_each_entry(port, &pcm->port_list, head) {
+		/* chmap is already set to 0 in caller */
+		memcpy(chmap, port->chmap, ARRAY_SIZE(port->chmap));
+	}
 }
 
 static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
@@ -1715,16 +1766,20 @@ static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
 	struct hdac_ext_device *edev = to_ehdac_device(hdac);
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
-	struct hdac_hdmi_port *port = pcm->port;
-	struct hdac_hdmi_pin *pin = port->pin;
+	struct hdac_hdmi_port *port;
+
+	if (list_empty(&pcm->port_list))
+		return;
 
 	if (pcm) {
 		mutex_lock(&pcm->lock);
-		port->chmap_set = true;
-		memcpy(port->chmap, chmap, ARRAY_SIZE(port->chmap));
-		if (prepared)
-			hdac_hdmi_setup_audio_infoframe(edev, pcm->cvt->nid,
-							pin->nid, port);
+		list_for_each_entry(port, &pcm->port_list, head) {
+			port->chmap_set = true;
+			memcpy(port->chmap, chmap, ARRAY_SIZE(port->chmap));
+			if (prepared)
+				hdac_hdmi_setup_audio_infoframe(edev, pcm->cvt->nid,
+								port->pin->nid, port);
+		}
 		mutex_unlock(&pcm->lock);
 	}
 }
@@ -1734,9 +1789,11 @@ static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
 	struct hdac_ext_device *edev = to_ehdac_device(hdac);
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
-	struct hdac_hdmi_port *port = pcm->port;
 
-	return port ? true:false;
+	if (list_empty(&pcm->port_list))
+		return false;
+
+	return true;
 }
 
 static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
@@ -1744,7 +1801,15 @@ static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
 	struct hdac_ext_device *edev = to_ehdac_device(hdac);
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx);
-	struct hdac_hdmi_port *port = pcm->port;
+	struct hdac_hdmi_port *port;
+
+	if (list_empty(&pcm->port_list))
+		return 0;
+
+	port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head);
+
+	if (!port)
+		return 0;
 
 	if (!port || !port->eld.eld_valid)
 		return 0;
@@ -1822,13 +1887,19 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
 	struct hdac_hdmi_pin *pin, *pin_next;
 	struct hdac_hdmi_cvt *cvt, *cvt_next;
 	struct hdac_hdmi_pcm *pcm, *pcm_next;
+	struct hdac_hdmi_port *port;
 	int i;
 
 	snd_soc_unregister_codec(&edev->hdac.dev);
 
 	list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) {
 		pcm->cvt = NULL;
-		pcm->port = NULL;
+		if (list_empty(&pcm->port_list))
+			continue;
+
+		list_for_each_entry(port, &pcm->port_list, head)
+			port = NULL;
+
 		list_del(&pcm->head);
 		kfree(pcm);
 	}
