All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio
@ 2016-09-20 13:46 jeeja.kp
  2016-09-20 13:46 ` [RFC 01/16] ASoC: hdac_hdmi: use audio component framework to read ELD jeeja.kp
                   ` (15 more replies)
  0 siblings, 16 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Display port 1.2 introduces new capability Multi-stream transport (MST)
which will allow multiple stream to route to single display port where
multiple monitors are connected. Multiple monitors will be connected by
a MST Hub or a monitor capable of daisy-chaining.

With MST support, a pin can support multiple ports and on each port a
monitor can be connected.

This patch series enables DP MST Audio by extending the current design
from pin to port.
1. With MST, Pin mux for CVT selection will be used to select CVT for
   Pin-port instead of Pin. So create the pin muxes accordingly.
2. Pin is marked as MST capable when connect event reports pipe as valid.
   if pipe is -1, then pin is not MST capable and default to port 0.
   if pipe is valid, then pin is MST capable and port = pipe.
3. For MST capable pin, select the device entry before configuring the pin
   widget verbs controlling the sink device operations.
4. Add support to handle multiple Port mapped to same converter by enabling
   all the ports and configuring the port when stream is prepared.
5. i915 acomp APIs are now used to read the ELD info and support is
   extended for MST port as well

Notes:
1. When Mutiple ports are mapped to same PCM, currenlty stream constrains
   will applied based on first port mapped. 

Jeeja KP (15):
  ASoC: hdac_hdmi: Begin to add support for DP Multi-stream Audio
  ASoC: Intel: Skylake: Add route change to rt286 machine
  ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine
  ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine
  ASoC: Intel: Skylake: Add route change to rt298 machine
  ASoC: Intel: Skylake: Add route change to da7219_max98357a machine
  ASoC: hdac_hdmi: Add support to handle MST capable pin
  ASoC: hdac_hdmi: Add MST verb support
  ASoc: hdac_hdmi: Configure pin verbs for MST
  ASoC: hdac_hdmi: Add support to handle Multiple Port to same PCM
  ASoC: Intel: Skylake: To support MST, add HDMI routes rt286 machine
  ASoC: Intel: Skylake: To support MST, add HDMI routes nau_max machine
  ASoC: Intel: Skylake: To support MST, add HDMI routes nau_ssm machine
  ASoC: Intel: Skylake: To support MST, add HDMI routes rt298 machine
  ASoC: Intel: Skylake: To support MST, add HDMI routes da7219_max
    machine

Sandeep Tayal (1):
  ASoC: hdac_hdmi: use audio component framework to read ELD

 sound/soc/codecs/hdac_hdmi.c                    | 919 ++++++++++++++----------
 sound/soc/intel/boards/bxt_da7219_max98357a.c   |  10 +-
 sound/soc/intel/boards/bxt_rt298.c              |  11 +-
 sound/soc/intel/boards/skl_nau88l25_max98357a.c |  12 +-
 sound/soc/intel/boards/skl_nau88l25_ssm4567.c   |  13 +-
 sound/soc/intel/boards/skl_rt286.c              |  10 +-
 6 files changed, 597 insertions(+), 378 deletions(-)

-- 
2.5.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC 01/16] ASoC: hdac_hdmi: use audio component framework to read ELD
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-25  5:58   ` Applied "ASoC: hdac_hdmi: use audio component framework to read ELD" to the asoc tree Mark Brown
  2016-09-20 13:46 ` [RFC 02/16] ASoC: hdac_hdmi: Begin to add support for DP Multi-stream Audio jeeja.kp
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP, Sandeep Tayal

From: Sandeep Tayal <sandeepx.tayal@intel.com>

With codec read sometimes the pin_sense shows invalid monitor present
and eld_valid. Currently driver polls for few times to get the valid
ELD data.

To avoid the latency, Instead of reading ELD from codec, read it
directly from the display driver using audio component framework.

Removed the direct codec helper functions.

Signed-off-by: Sandeep Tayal <sandeepx.tayal@intel.com>
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 201 ++++++++++++-------------------------------
 1 file changed, 56 insertions(+), 145 deletions(-)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index dc0129b..c504e98 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -46,6 +46,10 @@
 #define ELD_MAX_SIZE    256
 #define ELD_FIXED_BYTES	20
 
+#define ELD_VER_CEA_861D 2
+#define ELD_VER_PARTIAL 31
+#define ELD_MAX_MNL     16
+
 struct hdac_hdmi_cvt_params {
 	unsigned int channels_min;
 	unsigned int channels_max;
@@ -81,8 +85,6 @@ struct hdac_hdmi_pin {
 	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
 	struct hdac_hdmi_eld eld;
 	struct hdac_ext_device *edev;
-	int repoll_count;
-	struct delayed_work work;
 	struct mutex lock;
 	bool chmap_set;
 	unsigned char chmap[8]; /* ALSA API channel-map */
@@ -173,80 +175,6 @@ format_constraint:
 
 }
 
- /* HDMI ELD routines */
-static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec,
-				hda_nid_t nid, int byte_index)
-{
-	unsigned int val;
-
-	val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD,
-							byte_index);
-
-	dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n",
-					byte_index, val);
-
-	return val;
-}
-
-static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid)
-{
-	return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
-						 AC_DIPSIZE_ELD_BUF);
-}
-
-/*
- * This function queries the ELD size and ELD data and fills in the buffer
- * passed by user
- */
-static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid,
-			     unsigned char *buf, int *eld_size)
-{
-	int i, size, ret = 0;
-
-	/*
-	 * ELD size is initialized to zero in caller function. If no errors and
-	 * ELD is valid, actual eld_size is assigned.
-	 */
-
-	size = hdac_hdmi_get_eld_size(codec, nid);
-	if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
-		dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size);
-		return -ERANGE;
-	}
-
-	/* set ELD buffer */
-	for (i = 0; i < size; i++) {
-		unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i);
-		/*
-		 * Graphics driver might be writing to ELD buffer right now.
-		 * Just abort. The caller will repoll after a while.
-		 */
-		if (!(val & AC_ELDD_ELD_VALID)) {
-			dev_err(&codec->dev,
-				"HDMI: invalid ELD data byte %d\n", i);
-			ret = -EINVAL;
-			goto error;
-		}
-		val &= AC_ELDD_ELD_DATA;
-		/*
-		 * The first byte cannot be zero. This can happen on some DVI
-		 * connections. Some Intel chips may also need some 250ms delay
-		 * to return non-zero ELD data, even when the graphics driver
-		 * correctly writes ELD content before setting ELD_valid bit.
-		 */
-		if (!val && !i) {
-			dev_err(&codec->dev, "HDMI: 0 ELD data\n");
-			ret = -EINVAL;
-			goto error;
-		}
-		buf[i] = val;
-	}
-
-	*eld_size = size;
-error:
-	return ret;
-}
-
 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)
@@ -1059,32 +987,59 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
 	return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
 }
 
-static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
+static int  hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
 			struct hdac_hdmi_pin *pin)
 {
+	unsigned int ver, mnl;
+
+	ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
+						>> DRM_ELD_VER_SHIFT;
+
+	if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
+		dev_dbg(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver);
+		return -EINVAL;
+	}
+
+	mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
+		DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
+
+	if (mnl > ELD_MAX_MNL) {
+		dev_dbg(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl);
+		return -EINVAL;
+	}
+
 	pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER];
+
+	return 0;
 }
 
-static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
+static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
 {
 	struct hdac_ext_device *edev = pin->edev;
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm;
-	int val;
-
-	pin->repoll_count = repoll;
+	int size;
 
-	pm_runtime_get_sync(&edev->hdac.dev);
-	val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0,
-					AC_VERB_GET_PIN_SENSE, 0);
+	mutex_lock(&hdmi->pin_mutex);
+	pin->eld.monitor_present = false;
 
-	dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n",
-						val, pin->nid);
+	size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1,
+				&pin->eld.monitor_present, pin->eld.eld_buffer,
+				ELD_MAX_SIZE);
 
+	if (size > 0) {
+		size = min(size, ELD_MAX_SIZE);
+		if (hdac_hdmi_parse_eld(edev, pin) < 0)
+			size = -EINVAL;
+	}
 
-	mutex_lock(&hdmi->pin_mutex);
-	pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE);
-	pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV);
+	if (size > 0) {
+		pin->eld.eld_valid = true;
+		pin->eld.eld_size = size;
+	} else {
+		pin->eld.eld_valid = false;
+		pin->eld.eld_size = 0;
+	}
 
 	pcm = hdac_hdmi_get_pcm(edev, pin);
 
@@ -1106,66 +1061,23 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
 		}
 
 		mutex_unlock(&hdmi->pin_mutex);
-		goto put_hdac_device;
+		return;
 	}
 
 	if (pin->eld.monitor_present && pin->eld.eld_valid) {
-		/* TODO: use i915 component for reading ELD later */
-		if (hdac_hdmi_get_eld(&edev->hdac, pin->nid,
-				pin->eld.eld_buffer,
-				&pin->eld.eld_size) == 0) {
-
-			if (pcm) {
-				dev_dbg(&edev->hdac.dev,
-					"jack report for pcm=%d\n",
-					pcm->pcm_id);
-
-				snd_jack_report(pcm->jack, SND_JACK_AVOUT);
-			}
-			hdac_hdmi_parse_eld(edev, pin);
-
-			print_hex_dump_debug("ELD: ",
-					DUMP_PREFIX_OFFSET, 16, 1,
-					pin->eld.eld_buffer, pin->eld.eld_size,
-					true);
-		} else {
-			pin->eld.monitor_present = false;
-			pin->eld.eld_valid = false;
-
-			if (pcm) {
-				dev_dbg(&edev->hdac.dev,
-					"jack report for pcm=%d\n",
-					pcm->pcm_id);
+		if (pcm) {
+			dev_dbg(&edev->hdac.dev,
+				"jack report for pcm=%d\n",
+				pcm->pcm_id);
 
-				snd_jack_report(pcm->jack, 0);
-			}
+			snd_jack_report(pcm->jack, SND_JACK_AVOUT);
 		}
+
+		print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
+			  pin->eld.eld_buffer, pin->eld.eld_size, false);
 	}
 
 	mutex_unlock(&hdmi->pin_mutex);
-
-	/*
-	 * Sometimes the pin_sense may present invalid monitor
-	 * present and eld_valid. If ELD data is not valid, loop few
-	 * more times to get correct pin sense and valid ELD.
-	 */
-	if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll)
-		schedule_delayed_work(&pin->work, msecs_to_jiffies(300));
-
-put_hdac_device:
-	pm_runtime_put_sync(&edev->hdac.dev);
-}
-
-static void hdac_hdmi_repoll_eld(struct work_struct *work)
-{
-	struct hdac_hdmi_pin *pin =
-		container_of(to_delayed_work(work), struct hdac_hdmi_pin, work);
-
-	/* picked from legacy HDA driver */
-	if (pin->repoll_count++ > 6)
-		pin->repoll_count = 0;
-
-	hdac_hdmi_present_sense(pin, pin->repoll_count);
 }
 
 static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
@@ -1184,7 +1096,6 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
 
 	pin->edev = edev;
 	mutex_init(&pin->lock);
-	INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld);
 
 	return 0;
 }
@@ -1395,7 +1306,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
 
 	list_for_each_entry(pin, &hdmi->pin_list, head) {
 		if (pin->nid == pin_nid)
-			hdac_hdmi_present_sense(pin, 1);
+			hdac_hdmi_present_sense(pin);
 	}
 }
 
@@ -1496,7 +1407,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
 	}
 
 	list_for_each_entry(pin, &hdmi->pin_list, head)
-		hdac_hdmi_present_sense(pin, 1);
+		hdac_hdmi_present_sense(pin);
 
 	/* Imp: Store the card pointer in hda_codec */
 	edev->card = dapm->card->snd_card;
@@ -1561,7 +1472,7 @@ static void hdmi_codec_complete(struct device *dev)
 	 * all pins here.
 	 */
 	list_for_each_entry(pin, &hdmi->pin_list, head)
-		hdac_hdmi_present_sense(pin, 1);
+		hdac_hdmi_present_sense(pin);
 
 	pm_runtime_put_sync(&edev->hdac.dev);
 }
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 02/16] ASoC: hdac_hdmi: Begin to add support for DP Multi-stream Audio
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
  2016-09-20 13:46 ` [RFC 01/16] ASoC: hdac_hdmi: use audio component framework to read ELD jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 03/16] ASoC: Intel: Skylake: Add route change to rt286 machine jeeja.kp
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

With MST each pin contains several ports to which device can be
connected.

As a preparatory work to support DP MST this patch adds below changes:
1. Defines the port structure and moves all stream related information
   like ELD, converter list, chmap to port.
2. Creates ports for each pin based on the max_ports support.
3. Based on Pin-Port combination creates DAPM Mux widget instead of Pin
   to allow user to select a converter.
4. Port zero is the default port when pin does not support MST.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 454 +++++++++++++++++++++++++------------------
 1 file changed, 270 insertions(+), 184 deletions(-)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index c504e98..88d6dae 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -81,10 +81,17 @@ struct hdac_hdmi_eld {
 struct hdac_hdmi_pin {
 	struct list_head head;
 	hda_nid_t nid;
+	struct hdac_hdmi_port *ports;
+	int num_ports;
+	struct hdac_ext_device *edev;
+};
+
+struct hdac_hdmi_port {
+	int id;
+	struct hdac_hdmi_pin *pin;
 	int num_mux_nids;
 	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
 	struct hdac_hdmi_eld eld;
-	struct hdac_ext_device *edev;
 	struct mutex lock;
 	bool chmap_set;
 	unsigned char chmap[8]; /* ALSA API channel-map */
@@ -94,28 +101,35 @@ struct hdac_hdmi_pin {
 struct hdac_hdmi_pcm {
 	struct list_head head;
 	int pcm_id;
-	struct hdac_hdmi_pin *pin;
+	struct hdac_hdmi_port *port;
 	struct hdac_hdmi_cvt *cvt;
 	struct snd_jack *jack;
 };
 
-struct hdac_hdmi_dai_pin_map {
+struct hdac_hdmi_dai_port_map {
 	int dai_id;
-	struct hdac_hdmi_pin *pin;
+	struct hdac_hdmi_port *port;
 	struct hdac_hdmi_cvt *cvt;
 };
 
 struct hdac_hdmi_priv {
-	struct hdac_hdmi_dai_pin_map dai_map[HDA_MAX_CVTS];
+	struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS];
 	struct list_head pin_list;
 	struct list_head cvt_list;
 	struct list_head pcm_list;
 	int num_pin;
 	int num_cvt;
+	int num_ports;
 	struct mutex pin_mutex;
 	struct hdac_chmap chmap;
 };
 
+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);
+
 static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
 						int pcm_idx)
 {
@@ -219,13 +233,14 @@ struct dp_audio_infoframe {
 };
 
 static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
-				hda_nid_t cvt_nid, hda_nid_t pin_nid)
+				hda_nid_t cvt_nid, hda_nid_t pin_nid,
+				struct hdac_hdmi_port *port)
 {
 	uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
 	struct hdmi_audio_infoframe frame;
+	struct hdac_hdmi_pin *pin;
 	struct dp_audio_infoframe dp_ai;
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
-	struct hdac_hdmi_pin *pin;
 	u8 *dip;
 	int ret;
 	int i;
@@ -238,16 +253,16 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
 			break;
 	}
 
-	ca = snd_hdac_channel_allocation(&hdac->hdac, pin->eld.info.spk_alloc,
-			pin->channels, pin->chmap_set, true, pin->chmap);
+	ca = snd_hdac_channel_allocation(&hdac->hdac, port->eld.info.spk_alloc,
+			port->channels, port->chmap_set, true, port->chmap);
 
 	channels = snd_hdac_get_active_channels(ca);
 	hdmi->chmap.ops.set_channel_count(&hdac->hdac, cvt_nid, channels);
 
 	snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca,
-				pin->channels, pin->chmap, pin->chmap_set);
+				port->channels, port->chmap, port->chmap_set);
 
-	eld_buf = pin->eld.eld_buffer;
+	eld_buf = port->eld.eld_buffer;
 	conn_type = drm_eld_get_conn_type(eld_buf);
 
 	switch (conn_type) {
@@ -307,12 +322,14 @@ 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_pin_map *dai_map, unsigned int pwr_state)
+		struct hdac_hdmi_dai_port_map *dai_map, unsigned int pwr_state)
 {
+	struct hdac_hdmi_pin *pin = dai_map->port->pin;
+
 	/* Power up pin widget */
-	if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin->nid,
+	if (!snd_hdac_check_power_state(&edev->hdac, pin->nid,
 						pwr_state))
-		snd_hdac_codec_write(&edev->hdac, dai_map->pin->nid, 0,
+		snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
 			AC_VERB_SET_POWER_STATE, pwr_state);
 
 	/* Power up converter */
@@ -327,29 +344,34 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
 {
 	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
-	struct hdac_hdmi_dai_pin_map *dai_map;
-	struct hdac_hdmi_pin *pin;
+	struct hdac_hdmi_dai_port_map *dai_map;
+	struct hdac_hdmi_port *port;
 	struct hdac_ext_dma_params *dd;
 	int ret;
 
 	dai_map = &hdmi->dai_map[dai->id];
-	pin = dai_map->pin;
+	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",
 			dd->stream_tag,	dd->format);
 
-	mutex_lock(&pin->lock);
-	pin->channels = substream->runtime->channels;
+	hdac_hdmi_enable_cvt(hdac, dai_map);
+	ret = hdac_hdmi_enable_pin(hdac, dai_map);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&port->lock);
+	port->channels = substream->runtime->channels;
 
 	ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
-						dai_map->pin->nid);
-	mutex_unlock(&pin->lock);
+						port->pin->nid, port);
+	mutex_unlock(&port->lock);
 	if (ret < 0)
 		return ret;
 
 	return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid,
-			dai_map->pin->nid, dd->stream_tag, dd->format);
+			port->pin->nid, dd->stream_tag, dd->format);
 }
 
 static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
@@ -357,19 +379,20 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
 {
 	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
-	struct hdac_hdmi_dai_pin_map *dai_map;
-	struct hdac_hdmi_pin *pin;
+	struct hdac_hdmi_dai_port_map *dai_map;
+	struct hdac_hdmi_port *port;
 	struct hdac_ext_dma_params *dd;
 
 	dai_map = &hdmi->dai_map[dai->id];
-	pin = dai_map->pin;
+	port = dai_map->port;
 
-	if (!pin)
+	if (!port)
 		return -ENODEV;
 
-	if ((!pin->eld.monitor_present) || (!pin->eld.eld_valid)) {
-		dev_err(&hdac->hdac.dev, "device is not configured for this pin: %d\n",
-								pin->nid);
+	if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) {
+		dev_err(&hdac->hdac.dev,
+			"device is not configured for this pin:port%d:%d\n",
+					port->pin->nid, port->id);
 		return -ENODEV;
 	}
 
@@ -395,7 +418,7 @@ static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
 	struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai);
 	struct hdac_ext_dma_params *dd;
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
-	struct hdac_hdmi_dai_pin_map *dai_map;
+	struct hdac_hdmi_dai_port_map *dai_map;
 
 	dai_map = &hdmi->dai_map[dai->id];
 
@@ -410,7 +433,7 @@ static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
 }
 
 static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev,
-		struct hdac_hdmi_dai_pin_map *dai_map)
+		struct hdac_hdmi_dai_port_map *dai_map)
 {
 	/* Enable transmission */
 	snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
@@ -422,36 +445,37 @@ 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_pin_map *dai_map)
+		struct hdac_hdmi_dai_port_map *dai_map)
 {
 	int mux_idx;
-	struct hdac_hdmi_pin *pin = dai_map->pin;
+	struct hdac_hdmi_port *port = dai_map->port;
 
-	for (mux_idx = 0; mux_idx < pin->num_mux_nids; mux_idx++) {
-		if (pin->mux_nids[mux_idx] == dai_map->cvt->nid) {
-			snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
+	for (mux_idx = 0; mux_idx < port->num_mux_nids; mux_idx++) {
+		if (port->mux_nids[mux_idx] == dai_map->cvt->nid) {
+			snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
 					AC_VERB_SET_CONNECT_SEL, mux_idx);
 			break;
 		}
 	}
 
-	if (mux_idx == pin->num_mux_nids)
+	if (mux_idx == port->num_mux_nids)
 		return -EIO;
 
 	/* Enable out path for this pin widget */
-	snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
+	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);
 
-	snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
+	snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
 			AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
 
 	return 0;
 }
 
-static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac,
-					struct hdac_hdmi_pin *pin)
+static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *hdac,
+					struct hdac_hdmi_pin *pin,
+					struct hdac_hdmi_port *port)
 {
 	if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
 		dev_warn(&hdac->hdac.dev,
@@ -460,51 +484,52 @@ static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac,
 		return -EINVAL;
 	}
 
-	pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
-			pin->mux_nids, HDA_MAX_CONNECTIONS);
-	if (pin->num_mux_nids == 0)
-		dev_warn(&hdac->hdac.dev, "No connections found for pin: %d\n",
-								pin->nid);
+	port->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
+			port->mux_nids, HDA_MAX_CONNECTIONS);
+	if (port->num_mux_nids == 0)
+		dev_warn(&hdac->hdac.dev,
+			"No connections found for pin:port %d:%d\n",
+						pin->nid, port->id);
 
-	dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin: %d\n",
-			pin->num_mux_nids, pin->nid);
+	dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin:port %d:%d\n",
+			port->num_mux_nids, pin->nid, port->id);
 
-	return pin->num_mux_nids;
+	return port->num_mux_nids;
 }
 
 /*
- * Query pcm list and return pin widget to which stream is routed.
+ * Query pcm list and return port to which stream is routed.
  *
- * Also query connection list of the pin, to validate the cvt to pin map.
+ * Also query connection list of the pin, to validate the cvt to port map.
  *
- * Same stream rendering to multiple pins simultaneously can be done
- * possibly, but not supported for now in driver. So return the first pin
+ * Same stream rendering to multiple ports simultaneously can be done
+ * possibly, but not supported for now in driver. So return the first port
  * connected.
  */
-static struct hdac_hdmi_pin *hdac_hdmi_get_pin_from_cvt(
+static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
 			struct hdac_ext_device *edev,
 			struct hdac_hdmi_priv *hdmi,
 			struct hdac_hdmi_cvt *cvt)
 {
 	struct hdac_hdmi_pcm *pcm;
-	struct hdac_hdmi_pin *pin = NULL;
+	struct hdac_hdmi_port *port = NULL;
 	int ret, i;
 
 	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
 		if (pcm->cvt == cvt) {
-			pin = pcm->pin;
+			port = pcm->port;
 			break;
 		}
 	}
 
-	if (pin) {
-		ret = hdac_hdmi_query_pin_connlist(edev, pin);
+	if (port) {
+		ret = hdac_hdmi_query_port_connlist(edev, port->pin, port);
 		if (ret < 0)
 			return NULL;
 
-		for (i = 0; i < pin->num_mux_nids; i++) {
-			if (pin->mux_nids[i] == cvt->nid)
-				return pin;
+		for (i = 0; i < port->num_mux_nids; i++) {
+			if (port->mux_nids[i] == cvt->nid)
+				return port;
 		}
 	}
 
@@ -521,53 +546,49 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
 {
 	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
-	struct hdac_hdmi_dai_pin_map *dai_map;
+	struct hdac_hdmi_dai_port_map *dai_map;
 	struct hdac_hdmi_cvt *cvt;
-	struct hdac_hdmi_pin *pin;
+	struct hdac_hdmi_port *port;
 	int ret;
 
 	dai_map = &hdmi->dai_map[dai->id];
 
 	cvt = dai_map->cvt;
-	pin = hdac_hdmi_get_pin_from_cvt(hdac, hdmi, cvt);
+	port = hdac_hdmi_get_port_from_cvt(hdac, hdmi, cvt);
 
 	/*
 	 * To make PA and other userland happy.
 	 * userland scans devices so returning error does not help.
 	 */
-	if (!pin)
+	if (!port)
 		return 0;
 
-	if ((!pin->eld.monitor_present) ||
-			(!pin->eld.eld_valid)) {
+	if ((!port->eld.monitor_present) ||
+			(!port->eld.eld_valid)) {
 
 		dev_warn(&hdac->hdac.dev,
-			"Failed: montior present? %d ELD valid?: %d for pin: %d\n",
-			pin->eld.monitor_present, pin->eld.eld_valid, pin->nid);
+			"Failed: present?:%d ELD valid?:%d pin:port: %d:%d\n",
+			port->eld.monitor_present, port->eld.eld_valid,
+			port->pin->nid, port->id);
 
 		return 0;
 	}
 
-	dai_map->pin = pin;
-
-	hdac_hdmi_enable_cvt(hdac, dai_map);
-	ret = hdac_hdmi_enable_pin(hdac, dai_map);
-	if (ret < 0)
-		return ret;
+	dai_map->port = port;
 
 	ret = hdac_hdmi_eld_limit_formats(substream->runtime,
-				pin->eld.eld_buffer);
+				port->eld.eld_buffer);
 	if (ret < 0)
 		return ret;
 
 	return snd_pcm_hw_constraint_eld(substream->runtime,
-				pin->eld.eld_buffer);
+				port->eld.eld_buffer);
 }
 
 static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
 		struct snd_soc_dai *dai)
 {
-	struct hdac_hdmi_dai_pin_map *dai_map;
+	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;
@@ -589,11 +610,11 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
 {
 	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
-	struct hdac_hdmi_dai_pin_map *dai_map;
+	struct hdac_hdmi_dai_port_map *dai_map;
 
 	dai_map = &hdmi->dai_map[dai->id];
 
-	if (dai_map->pin) {
+	if (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,
@@ -601,16 +622,16 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
 
 		hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
 
-		snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
+		snd_hdac_codec_write(&hdac->hdac, dai_map->port->pin->nid, 0,
 			AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 
-		mutex_lock(&dai_map->pin->lock);
-		dai_map->pin->chmap_set = false;
-		memset(dai_map->pin->chmap, 0, sizeof(dai_map->pin->chmap));
-		dai_map->pin->channels = 0;
-		mutex_unlock(&dai_map->pin->lock);
+		mutex_lock(&dai_map->port->lock);
+		dai_map->port->chmap_set = false;
+		memset(dai_map->port->chmap, 0, sizeof(dai_map->port->chmap));
+		dai_map->port->channels = 0;
+		mutex_unlock(&dai_map->port->lock);
 
-		dai_map->pin = NULL;
+		dai_map->port = NULL;
 	}
 }
 
@@ -676,13 +697,16 @@ static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
 }
 
 static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
-					struct hdac_hdmi_pin *pin)
+					struct hdac_hdmi_port *port)
 {
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = NULL;
 
 	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
-		if (pcm->pin == pin)
+		if (!pcm->port)
+			continue;
+
+		if (pcm->port == port)
 			return pcm;
 	}
 
@@ -692,14 +716,14 @@ static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
 /*
  * Based on user selection, map the PINs with the PCMs.
  */
-static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol,
+static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
 	int ret;
 	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;
-	struct hdac_hdmi_pin *pin = w->priv;
+	struct hdac_hdmi_port *port = w->priv;
 	struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm = NULL;
@@ -709,18 +733,22 @@ static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol,
 	if (ret < 0)
 		return ret;
 
+	if (port == NULL)
+		return -EINVAL;
+
 	mutex_lock(&hdmi->pin_mutex);
 	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
-		if (pcm->pin == pin)
-			pcm->pin = NULL;
+		if (!pcm->port && pcm->port == port &&
+			pcm->port->id == port->id)
+			pcm->port = NULL;
 
 		/*
 		 * 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->pin) {
-			pcm->pin = pin;
-			if (pin->eld.monitor_present && pin->eld.eld_valid) {
+		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);
@@ -745,12 +773,13 @@ static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol,
  * care of selecting the right one and leaving all other inputs selected to
  * "NONE"
  */
-static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev,
-				struct hdac_hdmi_pin *pin,
+static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev,
+				struct hdac_hdmi_port *port,
 				struct snd_soc_dapm_widget *widget,
 				const char *widget_name)
 {
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
+	struct hdac_hdmi_pin *pin = port->pin;
 	struct snd_kcontrol_new *kc;
 	struct hdac_hdmi_cvt *cvt;
 	struct soc_enum *se;
@@ -769,7 +798,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev,
 	if (!se)
 		return -ENOMEM;
 
-	sprintf(kc_name, "Pin %d Input", pin->nid);
+	sprintf(kc_name, "Pin %d port %d Input", pin->nid, port->id);
 	kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL);
 	if (!kc->name)
 		return -ENOMEM;
@@ -778,7 +807,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev,
 	kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	kc->access = 0;
 	kc->info = snd_soc_info_enum_double;
-	kc->put = hdac_hdmi_set_pin_mux;
+	kc->put = hdac_hdmi_set_pin_port_mux;
 	kc->get = snd_soc_dapm_get_enum_double;
 
 	se->reg = SND_SOC_NOPM;
@@ -806,7 +835,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev,
 		return -ENOMEM;
 
 	return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget,
-			snd_soc_dapm_mux, pin, widget_name, NULL, kc, 1);
+			snd_soc_dapm_mux, port, widget_name, NULL, kc, 1);
 }
 
 /* Add cvt <- input <- mux route map */
@@ -817,10 +846,10 @@ static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev,
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	const struct snd_kcontrol_new *kc;
 	struct soc_enum *se;
-	int mux_index = hdmi->num_cvt + hdmi->num_pin;
+	int mux_index = hdmi->num_cvt + hdmi->num_ports;
 	int i, j;
 
-	for (i = 0; i < hdmi->num_pin; i++) {
+	for (i = 0; i < hdmi->num_ports; i++) {
 		kc = widgets[mux_index].kcontrol_news;
 		se = (struct soc_enum *)kc->private_value;
 		for (j = 0; j < hdmi->num_cvt; j++) {
@@ -839,17 +868,18 @@ static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev,
 /*
  * Widgets are added in the below sequence
  *	Converter widgets for num converters enumerated
- *	Pin widgets for num pins enumerated
- *	Pin mux widgets to represent connenction list of pin widget
+ *	Pin-port widgets for num ports for Pins enumerated
+ *	Pin-port mux widgets to represent connenction list of pin widget
  *
- * Total widgets elements = num_cvt + num_pin + num_pin;
+ * For each port, one Mux and One output widget is added
+ * Total widgets elements = num_cvt + (num_ports * 2);
  *
  * Routes are added as below:
- *	pin mux -> pin (based on num_pins)
- *	cvt -> "Input sel control" -> pin_mux
+ *	pin-port mux -> pin (based on num_ports)
+ *	cvt -> "Input sel control" -> pin-port_mux
  *
  * Total route elements:
- *	num_pins + (pin_muxes * num_cvt)
+ *	num_ports + (pin_muxes * num_cvt)
  */
 static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
 {
@@ -861,13 +891,13 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
 	char widget_name[NAME_SIZE];
 	struct hdac_hdmi_cvt *cvt;
 	struct hdac_hdmi_pin *pin;
-	int ret, i = 0, num_routes = 0;
+	int ret, i = 0, num_routes = 0, j;
 
 	if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
 		return -EINVAL;
 
 	widgets = devm_kzalloc(dapm->dev,
-		(sizeof(*widgets) * ((2 * hdmi->num_pin) + hdmi->num_cvt)),
+		(sizeof(*widgets) * ((2 * hdmi->num_ports) + hdmi->num_cvt)),
 		GFP_KERNEL);
 
 	if (!widgets)
@@ -885,31 +915,37 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
 	}
 
 	list_for_each_entry(pin, &hdmi->pin_list, head) {
-		sprintf(widget_name, "hif%d Output", pin->nid);
-		ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
-				snd_soc_dapm_output, &pin->nid,
-				widget_name, NULL, NULL, 0);
-		if (ret < 0)
-			return ret;
-		i++;
+		for (j = 0; j < pin->num_ports; j++) {
+			sprintf(widget_name, "hif%d-%d Output",
+				pin->nid, pin->ports[j].id);
+			ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
+					snd_soc_dapm_output, &pin->ports[j].id,
+					widget_name, NULL, NULL, 0);
+			if (ret < 0)
+				return ret;
+			i++;
+		}
 	}
 
 	/* DAPM widgets to represent the connection list to pin widget */
 	list_for_each_entry(pin, &hdmi->pin_list, head) {
-		sprintf(widget_name, "Pin %d Mux", pin->nid);
-		ret = hdac_hdmi_create_pin_muxs(edev, pin, &widgets[i],
-							widget_name);
-		if (ret < 0)
-			return ret;
-		i++;
+		for (j = 0; j < pin->num_ports; j++) {
+			sprintf(widget_name, "Pin%d-Port%d Mux",
+				pin->nid, pin->ports[j].id);
+			ret = hdac_hdmi_create_pin_port_muxs(edev,
+						&pin->ports[j], &widgets[i],
+						widget_name);
+			if (ret < 0)
+				return ret;
+			i++;
 
-		/* For cvt to pin_mux mapping */
-		num_routes += hdmi->num_cvt;
+			/* For cvt to pin_mux mapping */
+			num_routes += hdmi->num_cvt;
 
-		/* For pin_mux to pin mapping */
-		num_routes++;
+			/* For pin_mux to pin mapping */
+			num_routes++;
+		}
 	}
-
 	route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes),
 							GFP_KERNEL);
 	if (!route)
@@ -918,20 +954,21 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
 	i = 0;
 	/* Add pin <- NULL <- mux route map */
 	list_for_each_entry(pin, &hdmi->pin_list, head) {
-		int sink_index = i + hdmi->num_cvt;
-		int src_index = sink_index + hdmi->num_pin;
+		for (j = 0; j < pin->num_ports; j++) {
+			int sink_index = i + hdmi->num_cvt;
+			int src_index = sink_index + pin->num_ports;
 
-		hdac_hdmi_fill_route(&route[i],
+			hdac_hdmi_fill_route(&route[i],
 				widgets[sink_index].name, NULL,
 				widgets[src_index].name, NULL);
-		i++;
-
+			i++;
+		}
 	}
 
 	hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i);
 
 	snd_soc_dapm_new_controls(dapm, widgets,
-		((2 * hdmi->num_pin) + hdmi->num_cvt));
+		((2 * hdmi->num_ports) + hdmi->num_cvt));
 
 	snd_soc_dapm_add_routes(dapm, route, num_routes);
 	snd_soc_dapm_new_widgets(dapm->card);
@@ -943,7 +980,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
 static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
 {
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
-	struct hdac_hdmi_dai_pin_map *dai_map;
+	struct hdac_hdmi_dai_port_map *dai_map;
 	struct hdac_hdmi_cvt *cvt;
 	int dai_id = 0;
 
@@ -987,12 +1024,12 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
 	return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
 }
 
-static int  hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
-			struct hdac_hdmi_pin *pin)
+static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
+			struct hdac_hdmi_port *port)
 {
 	unsigned int ver, mnl;
 
-	ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
+	ver = (port->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
 						>> DRM_ELD_VER_SHIFT;
 
 	if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
@@ -1000,7 +1037,7 @@ static int  hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
 		return -EINVAL;
 	}
 
-	mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
+	mnl = (port->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
 		DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
 
 	if (mnl > ELD_MAX_MNL) {
@@ -1008,45 +1045,49 @@ static int  hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
 		return -EINVAL;
 	}
 
-	pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER];
+	port->eld.info.spk_alloc = port->eld.eld_buffer[DRM_ELD_SPEAKER];
 
 	return 0;
 }
 
-static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
+static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
+				    struct hdac_hdmi_port *port)
 {
 	struct hdac_ext_device *edev = pin->edev;
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm;
-	int size;
+	int size = 0;
+
+	if (!hdmi)
+		return;
 
 	mutex_lock(&hdmi->pin_mutex);
-	pin->eld.monitor_present = false;
+	port->eld.monitor_present = false;
 
 	size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1,
-				&pin->eld.monitor_present, pin->eld.eld_buffer,
+				&port->eld.monitor_present, port->eld.eld_buffer,
 				ELD_MAX_SIZE);
 
 	if (size > 0) {
 		size = min(size, ELD_MAX_SIZE);
-		if (hdac_hdmi_parse_eld(edev, pin) < 0)
+		if (hdac_hdmi_parse_eld(edev, port) < 0)
 			size = -EINVAL;
 	}
 
 	if (size > 0) {
-		pin->eld.eld_valid = true;
-		pin->eld.eld_size = size;
+		port->eld.eld_valid = true;
+		port->eld.eld_size = size;
 	} else {
-		pin->eld.eld_valid = false;
-		pin->eld.eld_size = 0;
+		port->eld.eld_valid = false;
+		port->eld.eld_size = 0;
 	}
 
-	pcm = hdac_hdmi_get_pcm(edev, pin);
+	pcm = hdac_hdmi_get_pcm(edev, port);
 
-	if (!pin->eld.monitor_present || !pin->eld.eld_valid) {
+	if (!port->eld.monitor_present || !port->eld.eld_valid) {
 
-		dev_dbg(&edev->hdac.dev, "%s: disconnect for pin %d\n",
-						__func__, pin->nid);
+		dev_dbg(&edev->hdac.dev, "%s: disconnect for pin:port %d:%d\n",
+						__func__, pin->nid, port->id);
 
 		/*
 		 * PCMs are not registered during device probe, so don't
@@ -1064,7 +1105,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
 		return;
 	}
 
-	if (pin->eld.monitor_present && pin->eld.eld_valid) {
+	if (port->eld.monitor_present && port->eld.eld_valid) {
 		if (pcm) {
 			dev_dbg(&edev->hdac.dev,
 				"jack report for pcm=%d\n",
@@ -1074,28 +1115,53 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
 		}
 
 		print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
-			  pin->eld.eld_buffer, pin->eld.eld_size, false);
-	}
+			  port->eld.eld_buffer, port->eld.eld_size, false);
 
+	}
 	mutex_unlock(&hdmi->pin_mutex);
 }
 
+static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
+				struct hdac_hdmi_pin *pin)
+{
+	struct hdac_hdmi_port *ports;
+	int max_ports = 3; /* FIXME  this will read from i915 acomp API*/
+	int i;
+
+	/*get max ports supported from i915 acomp interface */
+	ports = kzalloc(max_ports * sizeof(*ports), GFP_KERNEL);
+	if (!ports)
+		return -ENOMEM;
+
+	for (i=0; i < max_ports; i++) {
+		ports[i].id = i + 1;
+		ports[i].pin = pin;
+		mutex_init(&ports[i].lock);
+	}
+	pin->ports = ports;
+	pin->num_ports = max_ports;
+	return 0;
+}
+
 static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
 {
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pin *pin;
+	int ret;
 
 	pin = kzalloc(sizeof(*pin), GFP_KERNEL);
 	if (!pin)
 		return -ENOMEM;
 
 	pin->nid = nid;
+	pin->edev = edev;
+	ret = hdac_hdmi_add_ports(hdmi, pin);
+	if (ret < 0)
+		return ret;
 
 	list_add_tail(&pin->head, &hdmi->pin_list);
 	hdmi->num_pin++;
-
-	pin->edev = edev;
-	mutex_init(&pin->lock);
+	hdmi->num_ports += pin->num_ports;
 
 	return 0;
 }
@@ -1279,17 +1345,19 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
 	return hdac_hdmi_init_dai_map(edev);
 }
 
-static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
+static void hdac_hdmi_eld_notify_cb(void *aptr, int dport, int pipe)
 {
 	struct hdac_ext_device *edev = aptr;
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
-	struct hdac_hdmi_pin *pin;
+	struct hdac_hdmi_pin *pin = NULL;
+	struct hdac_hdmi_port *port = NULL;
 	struct snd_soc_codec *codec = edev->scodec;
 
 	/* Don't know how this mapping is derived */
-	hda_nid_t pin_nid = port + 0x04;
+	hda_nid_t pin_nid = dport + 0x04;
 
-	dev_dbg(&edev->hdac.dev, "%s: for pin: %d\n", __func__, pin_nid);
+	dev_dbg(&edev->hdac.dev, "%s: for pin:%d port=%d\n", __func__,
+							pin_nid, pipe);
 
 	/*
 	 * skip notification during system suspend (but not in runtime PM);
@@ -1305,9 +1373,18 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
 		return;
 
 	list_for_each_entry(pin, &hdmi->pin_list, head) {
-		if (pin->nid == pin_nid)
-			hdac_hdmi_present_sense(pin);
+		if (pin->nid != pin_nid)
+			continue;
+
+		if (pipe == -1) {
+			/* if not MST, default is port[0] */
+			port = &pin->ports[0];
+			break;
+		}
 	}
+
+	if (port)
+		hdac_hdmi_present_sense(pin, port);
 }
 
 static struct i915_audio_component_audio_ops aops = {
@@ -1378,7 +1455,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
 		snd_soc_component_get_dapm(&codec->component);
 	struct hdac_hdmi_pin *pin;
 	struct hdac_ext_link *hlink = NULL;
-	int ret;
+	int ret, i;
 
 	edev->scodec = codec;
 
@@ -1407,7 +1484,8 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
 	}
 
 	list_for_each_entry(pin, &hdmi->pin_list, head)
-		hdac_hdmi_present_sense(pin);
+		for (i = 0; i < pin->num_ports; i++)
+			hdac_hdmi_present_sense(pin, &pin->ports[i]);
 
 	/* Imp: Store the card pointer in hda_codec */
 	edev->card = dapm->card->snd_card;
@@ -1458,6 +1536,7 @@ static void hdmi_codec_complete(struct device *dev)
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pin *pin;
 	struct hdac_device *hdac = &edev->hdac;
+	int i;
 
 	/* Power up afg */
 	snd_hdac_codec_read(hdac, hdac->afg, 0,	AC_VERB_SET_POWER_STATE,
@@ -1472,7 +1551,8 @@ static void hdmi_codec_complete(struct device *dev)
 	 * all pins here.
 	 */
 	list_for_each_entry(pin, &hdmi->pin_list, head)
-		hdac_hdmi_present_sense(pin);
+		for (i = 0; i < pin->num_ports; i++)
+			hdac_hdmi_present_sense(pin, &pin->ports[i]);
 
 	pm_runtime_put_sync(&edev->hdac.dev);
 }
@@ -1493,13 +1573,13 @@ 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_pin *pin = pcm->pin;
+	struct hdac_hdmi_port *port = pcm->port;
 
 	/* chmap is already set to 0 in caller */
-	if (!pin)
+	if (!port)
 		return;
 
-	memcpy(chmap, pin->chmap, ARRAY_SIZE(pin->chmap));
+	memcpy(chmap, port->chmap, ARRAY_SIZE(port->chmap));
 }
 
 static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
@@ -1508,14 +1588,16 @@ 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_pin *pin = pcm->pin;
+	struct hdac_hdmi_port *port = pcm->port;
+	struct hdac_hdmi_pin *pin = port->pin;
 
-	mutex_lock(&pin->lock);
-	pin->chmap_set = true;
-	memcpy(pin->chmap, chmap, ARRAY_SIZE(pin->chmap));
+	mutex_lock(&port->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);
-	mutex_unlock(&pin->lock);
+		hdac_hdmi_setup_audio_infoframe(edev, pcm->cvt->nid,
+						pin->nid, port);
+	mutex_unlock(&port->lock);
 }
 
 static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
@@ -1523,9 +1605,9 @@ 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_pin *pin = pcm->pin;
+	struct hdac_hdmi_port *port = pcm->port;
 
-	return pin ? true:false;
+	return port ? true:false;
 }
 
 static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
@@ -1533,12 +1615,12 @@ 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_pin *pin = pcm->pin;
+	struct hdac_hdmi_port *port = pcm->port;
 
-	if (!pin || !pin->eld.eld_valid)
+	if (!port || !port->eld.eld_valid)
 		return 0;
 
-	return pin->eld.info.spk_alloc;
+	return port->eld.info.spk_alloc;
 }
 
 static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
@@ -1611,12 +1693,13 @@ 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;
+	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->pin = NULL;
+		pcm->port = NULL;
 		list_del(&pcm->head);
 		kfree(pcm);
 	}
@@ -1628,6 +1711,9 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
 	}
 
 	list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
+		for (i =0; i < pin->num_ports; i++)
+			pin->ports[i].pin = NULL;
+		kfree(pin->ports);
 		list_del(&pin->head);
 		kfree(pin);
 	}
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 03/16] ASoC: Intel: Skylake: Add route change to rt286 machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
  2016-09-20 13:46 ` [RFC 01/16] ASoC: hdac_hdmi: use audio component framework to read ELD jeeja.kp
  2016-09-20 13:46 ` [RFC 02/16] ASoC: hdac_hdmi: Begin to add support for DP Multi-stream Audio jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2017-02-04 12:12   ` Applied "ASoC: Intel: Skylake: Add route change to rt286 machine" to the asoc tree Mark Brown
  2016-09-20 13:46 ` [RFC 04/16] ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine jeeja.kp
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To support MST moved pin to port, this changes the routes based on port.
So change the route in skl_rt286 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/skl_rt286.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c
index 88c61e8..367fc36 100644
--- a/sound/soc/intel/boards/skl_rt286.c
+++ b/sound/soc/intel/boards/skl_rt286.c
@@ -94,9 +94,9 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
 	{"DMIC1 Pin", NULL, "DMIC2"},
 	{"DMic", NULL, "SoC DMIC"},
 
-	{"HDMI1", NULL, "hif5 Output"},
-	{"HDMI2", NULL, "hif6 Output"},
-	{"HDMI3", NULL, "hif7 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI3", NULL, "hif7-0 Output"},
 
 	/* CODEC BE connections */
 	{ "AIF1 Playback", NULL, "ssp0 Tx"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 04/16] ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (2 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 03/16] ASoC: Intel: Skylake: Add route change to rt286 machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2017-02-08 18:34   ` Applied "ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine" to the asoc tree Mark Brown
  2016-09-20 13:46 ` [RFC 05/16] ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine jeeja.kp
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To support MST moved pin to port, this changes the routes based on port.
So change the route in nau88l25_max98357a machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/skl_nau88l25_max98357a.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
index 25db5be..9da1b64 100644
--- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c
+++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
@@ -111,8 +111,8 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_SPK("Spk", NULL),
 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-	SND_SOC_DAPM_SPK("DP", NULL),
-	SND_SOC_DAPM_SPK("HDMI", NULL),
+	SND_SOC_DAPM_SPK("DP1", NULL),
+	SND_SOC_DAPM_SPK("DP2", NULL),
 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMD),
@@ -130,8 +130,8 @@ static const struct snd_soc_dapm_route skylake_map[] = {
 	{ "MIC", NULL, "Headset Mic" },
 	{ "DMic", NULL, "SoC DMIC" },
 
-	{"HDMI", NULL, "hif5 Output"},
-	{"DP", NULL, "hif6 Output"},
+	{"DP1", NULL, "hif5-0 Output"},
+	{"DP2", NULL, "hif6-0 Output"},
 
 	/* CODEC BE connections */
 	{ "HiFi Playback", NULL, "ssp0 Tx" },
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 05/16] ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (3 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 04/16] ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2017-02-08 18:34   ` Applied "ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine" to the asoc tree Mark Brown
  2016-09-20 13:46 ` [RFC 06/16] ASoC: Intel: Skylake: Add route change to rt298 machine jeeja.kp
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To support MST moved pin to port, this changes the routes based on port.
So change the route in nau88l25_ssm4567 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
index 69c5d5d..d1f843b 100644
--- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
+++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
@@ -115,8 +115,8 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
 	SND_SOC_DAPM_SPK("Left Speaker", NULL),
 	SND_SOC_DAPM_SPK("Right Speaker", NULL),
 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-	SND_SOC_DAPM_SPK("DP", NULL),
-	SND_SOC_DAPM_SPK("HDMI", NULL),
+	SND_SOC_DAPM_SPK("DP1", NULL),
+	SND_SOC_DAPM_SPK("DP2", NULL),
 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMD),
@@ -135,8 +135,9 @@ static const struct snd_soc_dapm_route skylake_map[] = {
 	{"MIC", NULL, "Headset Mic"},
 	{"DMic", NULL, "SoC DMIC"},
 
-	{"HDMI", NULL, "hif5 Output"},
-	{"DP", NULL, "hif6 Output"},
+	{"DP1", NULL, "hif5-0 Output"},
+	{"DP2", NULL, "hif6-0 Output"},
+
 	/* CODEC BE connections */
 	{ "Left Playback", NULL, "ssp0 Tx"},
 	{ "Right Playback", NULL, "ssp0 Tx"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 06/16] ASoC: Intel: Skylake: Add route change to rt298 machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (4 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 05/16] ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2017-02-08 18:34   ` Applied "ASoC: Intel: bxt: Add route change to rt298 machine" to the asoc tree Mark Brown
  2016-09-20 13:46 ` [RFC 07/16] ASoC: Intel: Skylake: Add route change to da7219_max98357a machine jeeja.kp
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To support MST moved pin to port, this changes the routes based on
port. So change the route in bxt_rt298 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/bxt_rt298.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c
index 253d7bf..3052797 100644
--- a/sound/soc/intel/boards/bxt_rt298.c
+++ b/sound/soc/intel/boards/bxt_rt298.c
@@ -82,9 +82,9 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
 	{"DMIC1 Pin", NULL, "DMIC2"},
 	{"DMic", NULL, "SoC DMIC"},
 
-	{"HDMI1", NULL, "hif5 Output"},
-	{"HDMI2", NULL, "hif6 Output"},
-	{"HDMI3", NULL, "hif7 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI2", NULL, "hif7-0 Output"},
 
 	/* CODEC BE connections */
 	{ "AIF1 Playback", NULL, "ssp5 Tx"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 07/16] ASoC: Intel: Skylake: Add route change to da7219_max98357a machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (5 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 06/16] ASoC: Intel: Skylake: Add route change to rt298 machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2017-02-04 12:12   ` Applied "ASoC: Intel: bxt: Add route change to da7219_max98357a machine" to the asoc tree Mark Brown
  2016-09-20 13:46 ` [RFC 08/16] ASoC: hdac_hdmi: Add support to handle MST capable pin jeeja.kp
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To support MST moved pin to port, this changes the routes based on
port. So change the route in bxt_da7219_max98357a machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/bxt_da7219_max98357a.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c
index 3774b11..c4dca26 100644
--- a/sound/soc/intel/boards/bxt_da7219_max98357a.c
+++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c
@@ -82,9 +82,9 @@ static const struct snd_soc_dapm_route broxton_map[] = {
 	{"codec0_in", NULL, "ssp1 Rx"},
 	{"ssp1 Rx", NULL, "Capture"},
 
-	{"HDMI1", NULL, "hif5 Output"},
-	{"HDMI2", NULL, "hif6 Output"},
-	{"HDMI3", NULL, "hif7 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI2", NULL, "hif7-0 Output"},
 
 	{"hifi3", NULL, "iDisp3 Tx"},
 	{"iDisp3 Tx", NULL, "iDisp3_out"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 08/16] ASoC: hdac_hdmi: Add support to handle MST capable pin
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (6 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 07/16] ASoC: Intel: Skylake: Add route change to da7219_max98357a machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 09/16] ASoC: hdac_hdmi: Add MST verb support jeeja.kp
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To handle Jack event and Configure the Pin widget for MST capable pin,
this patch adds:
1. Flag to identify the pin is MST capable.
2. In notify callback(), based on the pipe and port information marks
   if the port is mst_capable. In case of Non MST, port is defaulted to
   zero.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 88d6dae..c9f4d4a 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -81,6 +81,7 @@ struct hdac_hdmi_eld {
 struct hdac_hdmi_pin {
 	struct list_head head;
 	hda_nid_t nid;
+	bool is_mst_capable;
 	struct hdac_hdmi_port *ports;
 	int num_ports;
 	struct hdac_ext_device *edev;
@@ -1057,6 +1058,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm;
 	int size = 0;
+	int port_id;
 
 	if (!hdmi)
 		return;
@@ -1064,7 +1066,9 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
 	mutex_lock(&hdmi->pin_mutex);
 	port->eld.monitor_present = false;
 
-	size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1,
+	port_id = (pin->is_mst_capable)? port->id: -1;
+
+	size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, port_id,
 				&port->eld.monitor_present, port->eld.eld_buffer,
 				ELD_MAX_SIZE);
 
@@ -1154,6 +1158,7 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
 		return -ENOMEM;
 
 	pin->nid = nid;
+	pin->is_mst_capable = false;
 	pin->edev = edev;
 	ret = hdac_hdmi_add_ports(hdmi, pin);
 	if (ret < 0)
@@ -1352,6 +1357,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int dport, int pipe)
 	struct hdac_hdmi_pin *pin = NULL;
 	struct hdac_hdmi_port *port = NULL;
 	struct snd_soc_codec *codec = edev->scodec;
+	int i;
 
 	/* Don't know how this mapping is derived */
 	hda_nid_t pin_nid = dport + 0x04;
@@ -1377,13 +1383,23 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int dport, int pipe)
 			continue;
 
 		if (pipe == -1) {
+			pin->is_mst_capable = false;
 			/* if not MST, default is port[0] */
 			port = &pin->ports[0];
-			break;
+			goto out;
+		} else {
+			for (i=0; i < pin->num_ports; i++) {
+				pin->is_mst_capable = true;
+				if (pin->ports[i].id == pipe) {
+					port = &pin->ports[i];
+					goto out;
+				}
+			}
 		}
 	}
 
-	if (port)
+out:
+	if (pin && port)
 		hdac_hdmi_present_sense(pin, port);
 }
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 09/16] ASoC: hdac_hdmi: Add MST verb support
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (7 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 08/16] ASoC: hdac_hdmi: Add support to handle MST capable pin jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 10/16] ASoc: hdac_hdmi: Configure pin verbs for MST jeeja.kp
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To support DP MST audio, new pin verbs/params are added. This patch
adds helper functions to do following:
1. To set a specific port
2. To get the currently selected port
3. To get the length of port.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index c9f4d4a..d99eb9c 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -125,6 +125,75 @@ struct hdac_hdmi_priv {
 	struct hdac_chmap chmap;
 };
 
+/* MST supported verbs */
+/*
+ * Get the no devices that can be connected to a port on the Pin widget.
+ */
+static int hdac_hdmi_get_port_len(struct hdac_ext_device *hdac, hda_nid_t nid)
+{
+	unsigned int caps;
+	unsigned int type, param;
+
+	caps = get_wcaps(&hdac->hdac, nid);
+	type = get_wcaps_type(caps);
+
+	if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN))
+		return 0;
+
+	param = snd_hdac_read_parm_uncached(&hdac->hdac, nid,
+					AC_PAR_DEVLIST_LEN);
+	if (param == -1)
+		return param;
+
+	return param & AC_DEV_LIST_LEN_MASK;
+}
+
+/*
+ * Get the port entry select on the pin. Return the port entry
+ * id selected on the pin. Return 0 means the first port entry
+ * is selected or MST is not supported.
+ */
+static int hdac_hdmi_port_select_get(struct hdac_ext_device *hdac,
+					struct hdac_hdmi_port *port)
+{
+	return snd_hdac_codec_read(&hdac->hdac, port->pin->nid,
+				0, AC_VERB_GET_DEVICE_SEL, 0);
+}
+
+/*
+ * Sets the selected port entry for the configuring Pin widget verb.
+ * returns error if port set is not equal to port get otherwise success
+ */
+static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac,
+					struct hdac_hdmi_port *port)
+{
+	int num_ports;
+
+	if (!port->pin->is_mst_capable)
+		return 0;
+
+	/* AC_PAR_DEVLIST_LEN is 0 based. */
+	num_ports = hdac_hdmi_get_port_len(hdac, port->pin->nid);
+
+	if (num_ports < 0)
+		return -EIO;
+	/*
+	 * Device List Length is a 0 based integer value indicating the
+	 * number of sink device that a MST Pin Widget can support.
+	 */
+	if (num_ports +1  <port->id)
+		return 0;
+
+	snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
+			AC_VERB_SET_DEVICE_SEL, port->id);
+
+	if (port->id != hdac_hdmi_port_select_get(hdac, port))
+		return -EIO;
+
+	dev_dbg(&hdac->hdac.dev, "Selected the port=%d\n", port->id);
+	return 0;
+}
+
 static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev,
 		                struct hdac_hdmi_dai_port_map *dai_map);
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 10/16] ASoc: hdac_hdmi: Configure pin verbs for MST
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (8 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 09/16] ASoC: hdac_hdmi: Add MST verb support jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 11/16] ASoC: hdac_hdmi: Add support to handle Multiple Port to same PCM jeeja.kp
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

To enable stream on to specific port which is MST capable pin, before
configuring the pin widget verb, Port need to be selected.

When Port is selected, all the Pin widget verb controlling the sink
device operation will be directed to selected port. So add port
selection before configuring the pin widget verb.

Since the port select can change between pcm, need to protect the
selection of port and the configuration of pin widget verb. So moved
the port lock to pcm lock.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 80 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 62 insertions(+), 18 deletions(-)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index d99eb9c..618af31 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -93,7 +93,6 @@ struct hdac_hdmi_port {
 	int num_mux_nids;
 	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
 	struct hdac_hdmi_eld eld;
-	struct mutex lock;
 	bool chmap_set;
 	unsigned char chmap[8]; /* ALSA API channel-map */
 	int channels; /* current number of channels */
@@ -101,6 +100,7 @@ struct hdac_hdmi_port {
 
 struct hdac_hdmi_pcm {
 	struct list_head head;
+	struct mutex lock;
 	int pcm_id;
 	struct hdac_hdmi_port *port;
 	struct hdac_hdmi_cvt *cvt;
@@ -125,6 +125,20 @@ struct hdac_hdmi_priv {
 	struct hdac_chmap chmap;
 };
 
+static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm_from_cvt(
+			struct hdac_hdmi_priv *hdmi,
+			struct hdac_hdmi_cvt *cvt)
+{
+	struct hdac_hdmi_pcm *pcm = NULL;
+
+	list_for_each_entry(pcm, &hdmi->pcm_list, head) {
+		if (pcm->cvt == cvt)
+			break;
+	}
+
+	return pcm;
+}
+
 /* MST supported verbs */
 /*
  * Get the no devices that can be connected to a port on the Pin widget.
@@ -323,6 +337,9 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
 			break;
 	}
 
+	if (hdac_hdmi_port_select_set(hdac, port) < 0)
+		return -EIO;
+
 	ca = snd_hdac_channel_allocation(&hdac->hdac, port->eld.info.spk_alloc,
 			port->channels, port->chmap_set, true, port->chmap);
 
@@ -416,6 +433,7 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
 	struct hdac_hdmi_dai_port_map *dai_map;
 	struct hdac_hdmi_port *port;
+	struct hdac_hdmi_pcm *pcm;
 	struct hdac_ext_dma_params *dd;
 	int ret;
 
@@ -427,16 +445,21 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
 			dd->stream_tag,	dd->format);
 
 	hdac_hdmi_enable_cvt(hdac, dai_map);
+	pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
+
+	if (!pcm)
+		return -EIO;
+
+	mutex_lock(&pcm->lock);
 	ret = hdac_hdmi_enable_pin(hdac, dai_map);
 	if (ret < 0)
 		return ret;
 
-	mutex_lock(&port->lock);
 	port->channels = substream->runtime->channels;
 
 	ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
 						port->pin->nid, port);
-	mutex_unlock(&port->lock);
+	mutex_unlock(&pcm->lock);
 	if (ret < 0)
 		return ret;
 
@@ -520,6 +543,10 @@ static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac,
 	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) {
 			snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0,
@@ -547,6 +574,11 @@ static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *hdac,
 					struct hdac_hdmi_pin *pin,
 					struct hdac_hdmi_port *port)
 {
+
+	/* set the device if pin is mst_capable */
+	if (hdac_hdmi_port_select_set(hdac, port) < 0)
+		return -EIO;
+
 	if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
 		dev_warn(&hdac->hdac.dev,
 			"HDMI: pin %d wcaps %#x does not support connection list\n",
@@ -593,7 +625,10 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
 	}
 
 	if (port) {
+		mutex_lock(&pcm->lock);
 		ret = hdac_hdmi_query_port_connlist(edev, port->pin, port);
+		mutex_unlock(&pcm->lock);
+
 		if (ret < 0)
 			return NULL;
 
@@ -681,25 +716,32 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
 	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
 	struct hdac_hdmi_priv *hdmi = hdac->private_data;
 	struct hdac_hdmi_dai_port_map *dai_map;
+	struct hdac_hdmi_port *port;
+	struct hdac_hdmi_pcm *pcm;
 
 	dai_map = &hdmi->dai_map[dai->id];
 
-	if (dai_map->port) {
+	pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, 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);
 
-		hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
-
-		snd_hdac_codec_write(&hdac->hdac, dai_map->port->pin->nid, 0,
-			AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+		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);
 
-		mutex_lock(&dai_map->port->lock);
+			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(&dai_map->port->lock);
+		mutex_unlock(&pcm->lock);
 
 		dai_map->port = NULL;
 	}
@@ -1209,7 +1251,6 @@ static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
 	for (i=0; i < max_ports; i++) {
 		ports[i].id = i + 1;
 		ports[i].pin = pin;
-		mutex_init(&ports[i].lock);
 	}
 	pin->ports = ports;
 	pin->num_ports = max_ports;
@@ -1510,6 +1551,7 @@ 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;
+	mutex_init(&pcm->lock);
 
 	snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device);
 	if (snd_pcm) {
@@ -1676,13 +1718,15 @@ static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
 	struct hdac_hdmi_port *port = pcm->port;
 	struct hdac_hdmi_pin *pin = port->pin;
 
-	mutex_lock(&port->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);
-	mutex_unlock(&port->lock);
+	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);
+		mutex_unlock(&pcm->lock);
+	}
 }
 
 static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 11/16] ASoC: hdac_hdmi: Add support to handle Multiple Port to same PCM
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (9 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 10/16] ASoc: hdac_hdmi: Configure pin verbs for MST jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 12/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt286 machine jeeja.kp
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Since we have the MST feature enabled and Pin-Port mux for user to
select the converter routing, Multiple port mapping to same converter
needs to be supported.

This patch the following changes to support Multiple port mapped to same
converter.
1. Jack reporting in case where Multiple port are attached to same PCM.
2. Enable all the port if the device connected in pcm prepare.
3. Configure Audio frame for all ports in pcm prepare.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 295 +++++++++++++++++++++++++++----------------
 1 file changed, 183 insertions(+), 112 deletions(-)

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);
 	}
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 12/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt286 machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (10 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 11/16] ASoC: hdac_hdmi: Add support to handle Multiple Port to same PCM jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 13/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_max machine jeeja.kp
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Skylake platform support maximum of 3 ports per pin, so add the
additional routes for rt286 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/skl_rt286.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c
index 367fc36..4b95e7f 100644
--- a/sound/soc/intel/boards/skl_rt286.c
+++ b/sound/soc/intel/boards/skl_rt286.c
@@ -96,7 +96,11 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
 
 	{"HDMI1", NULL, "hif5-0 Output"},
 	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI2", NULL, "hif6-1 Output"},
+	{"HDMI2", NULL, "hif6-2 Output"},
 	{"HDMI3", NULL, "hif7-0 Output"},
+	{"HDMI3", NULL, "hif7-1 Output"},
+	{"HDMI3", NULL, "hif7-2 Output"},
 
 	/* CODEC BE connections */
 	{ "AIF1 Playback", NULL, "ssp0 Tx"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 13/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_max machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (11 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 12/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt286 machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 14/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_ssm machine jeeja.kp
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Skylake platform support maximum of 3 ports per pin, so add the
additional routes for nau88l25_max98357a machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/skl_nau88l25_max98357a.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
index 9da1b64..ac77308 100644
--- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c
+++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
@@ -131,7 +131,11 @@ static const struct snd_soc_dapm_route skylake_map[] = {
 	{ "DMic", NULL, "SoC DMIC" },
 
 	{"DP1", NULL, "hif5-0 Output"},
+	{"DP1", NULL, "hif5-1 Output"},
+	{"DP1", NULL, "hif5-2 Output"},
 	{"DP2", NULL, "hif6-0 Output"},
+	{"DP2", NULL, "hif6-1 Output"},
+	{"DP2", NULL, "hif6-2 Output"},
 
 	/* CODEC BE connections */
 	{ "HiFi Playback", NULL, "ssp0 Tx" },
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 14/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_ssm machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (12 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 13/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_max machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 15/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt298 machine jeeja.kp
  2016-09-20 13:46 ` [RFC 16/16] ASoC: Intel: Skylake: To support MST, add HDMI routes da7219_max machine jeeja.kp
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Skylake platform support maximum of 3 ports per pin, so add the
additional routes for nau88l25_ssm4567 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
index d1f843b..5901340 100644
--- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
+++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
@@ -136,7 +136,11 @@ static const struct snd_soc_dapm_route skylake_map[] = {
 	{"DMic", NULL, "SoC DMIC"},
 
 	{"DP1", NULL, "hif5-0 Output"},
+	{"DP1", NULL, "hif5-1 Output"},
+	{"DP1", NULL, "hif5-2 Output"},
 	{"DP2", NULL, "hif6-0 Output"},
+	{"DP2", NULL, "hif6-1 Output"},
+	{"DP2", NULL, "hif6-2 Output"},
 
 	/* CODEC BE connections */
 	{ "Left Playback", NULL, "ssp0 Tx"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 15/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt298 machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (13 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 14/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_ssm machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  2016-09-20 13:46 ` [RFC 16/16] ASoC: Intel: Skylake: To support MST, add HDMI routes da7219_max machine jeeja.kp
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Skylake platform support maximum of 3 ports per pin, so add the
additional routes for rt286 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/bxt_rt298.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c
index 3052797..a99a91f 100644
--- a/sound/soc/intel/boards/bxt_rt298.c
+++ b/sound/soc/intel/boards/bxt_rt298.c
@@ -83,8 +83,13 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
 	{"DMic", NULL, "SoC DMIC"},
 
 	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
 	{"HDMI2", NULL, "hif6-0 Output"},
-	{"HDMI2", NULL, "hif7-0 Output"},
+	{"HDMI2", NULL, "hif6-1 Output"},
+	{"HDMI2", NULL, "hif6-2 Output"},
+	{"HDMI3", NULL, "hif7-0 Output"},
+	{"HDMI3", NULL, "hif7-1 Output"},
+	{"HDMI3", NULL, "hif7-2 Output"},
 
 	/* CODEC BE connections */
 	{ "AIF1 Playback", NULL, "ssp5 Tx"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC 16/16] ASoC: Intel: Skylake: To support MST, add HDMI routes da7219_max machine
  2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
                   ` (14 preceding siblings ...)
  2016-09-20 13:46 ` [RFC 15/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt298 machine jeeja.kp
@ 2016-09-20 13:46 ` jeeja.kp
  15 siblings, 0 replies; 23+ messages in thread
From: jeeja.kp @ 2016-09-20 13:46 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

From: Jeeja KP <jeeja.kp@intel.com>

Skylake platform support maximum of 3 ports per pin, so add the
additional routes for bxt_da7219_max98357a  machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
---
 sound/soc/intel/boards/bxt_da7219_max98357a.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c
index c4dca26..5953c4f 100644
--- a/sound/soc/intel/boards/bxt_da7219_max98357a.c
+++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c
@@ -84,7 +84,11 @@ static const struct snd_soc_dapm_route broxton_map[] = {
 
 	{"HDMI1", NULL, "hif5-0 Output"},
 	{"HDMI2", NULL, "hif6-0 Output"},
-	{"HDMI2", NULL, "hif7-0 Output"},
+	{"HDMI2", NULL, "hif6-1 Output"},
+	{"HDMI2", NULL, "hif6-2 Output"},
+	{"HDMI3", NULL, "hif7-0 Output"},
+	{"HDMI3", NULL, "hif7-1 Output"},
+	{"HDMI3", NULL, "hif7-2 Output"},
 
 	{"hifi3", NULL, "iDisp3 Tx"},
 	{"iDisp3 Tx", NULL, "iDisp3_out"},
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Applied "ASoC: hdac_hdmi: use audio component framework to read ELD" to the asoc tree
  2016-09-20 13:46 ` [RFC 01/16] ASoC: hdac_hdmi: use audio component framework to read ELD jeeja.kp
@ 2016-09-25  5:58   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2016-09-25  5:58 UTC (permalink / raw)
  To: Sandeep Tayal
  Cc: alsa-devel, tiwai, patches.audio, broonie, liam.r.girdwood, Jeeja KP

The patch

   ASoC: hdac_hdmi: use audio component framework to read ELD

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From fe27f4e0545d3fc1b0518fafb4fe0460d757651d Mon Sep 17 00:00:00 2001
From: Sandeep Tayal <sandeepx.tayal@intel.com>
Date: Tue, 20 Sep 2016 19:16:05 +0530
Subject: [PATCH] ASoC: hdac_hdmi: use audio component framework to read ELD

With codec read sometimes the pin_sense shows invalid monitor present
and eld_valid. Currently driver polls for few times to get the valid
ELD data.

To avoid the latency, Instead of reading ELD from codec, read it
directly from the display driver using audio component framework.

Removed the direct codec helper functions.

Signed-off-by: Sandeep Tayal <sandeepx.tayal@intel.com>
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/hdac_hdmi.c | 201 ++++++++++++-------------------------------
 1 file changed, 56 insertions(+), 145 deletions(-)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 4e181b270d95..537f61aa27fa 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -46,6 +46,10 @@
 #define ELD_MAX_SIZE    256
 #define ELD_FIXED_BYTES	20
 
+#define ELD_VER_CEA_861D 2
+#define ELD_VER_PARTIAL 31
+#define ELD_MAX_MNL     16
+
 struct hdac_hdmi_cvt_params {
 	unsigned int channels_min;
 	unsigned int channels_max;
@@ -81,8 +85,6 @@ struct hdac_hdmi_pin {
 	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
 	struct hdac_hdmi_eld eld;
 	struct hdac_ext_device *edev;
-	int repoll_count;
-	struct delayed_work work;
 	struct mutex lock;
 	bool chmap_set;
 	unsigned char chmap[8]; /* ALSA API channel-map */
@@ -173,80 +175,6 @@ format_constraint:
 
 }
 
- /* HDMI ELD routines */
-static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec,
-				hda_nid_t nid, int byte_index)
-{
-	unsigned int val;
-
-	val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD,
-							byte_index);
-
-	dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n",
-					byte_index, val);
-
-	return val;
-}
-
-static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid)
-{
-	return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
-						 AC_DIPSIZE_ELD_BUF);
-}
-
-/*
- * This function queries the ELD size and ELD data and fills in the buffer
- * passed by user
- */
-static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid,
-			     unsigned char *buf, int *eld_size)
-{
-	int i, size, ret = 0;
-
-	/*
-	 * ELD size is initialized to zero in caller function. If no errors and
-	 * ELD is valid, actual eld_size is assigned.
-	 */
-
-	size = hdac_hdmi_get_eld_size(codec, nid);
-	if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
-		dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size);
-		return -ERANGE;
-	}
-
-	/* set ELD buffer */
-	for (i = 0; i < size; i++) {
-		unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i);
-		/*
-		 * Graphics driver might be writing to ELD buffer right now.
-		 * Just abort. The caller will repoll after a while.
-		 */
-		if (!(val & AC_ELDD_ELD_VALID)) {
-			dev_err(&codec->dev,
-				"HDMI: invalid ELD data byte %d\n", i);
-			ret = -EINVAL;
-			goto error;
-		}
-		val &= AC_ELDD_ELD_DATA;
-		/*
-		 * The first byte cannot be zero. This can happen on some DVI
-		 * connections. Some Intel chips may also need some 250ms delay
-		 * to return non-zero ELD data, even when the graphics driver
-		 * correctly writes ELD content before setting ELD_valid bit.
-		 */
-		if (!val && !i) {
-			dev_err(&codec->dev, "HDMI: 0 ELD data\n");
-			ret = -EINVAL;
-			goto error;
-		}
-		buf[i] = val;
-	}
-
-	*eld_size = size;
-error:
-	return ret;
-}
-
 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)
@@ -1059,32 +987,59 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
 	return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
 }
 
-static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
+static int  hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
 			struct hdac_hdmi_pin *pin)
 {
+	unsigned int ver, mnl;
+
+	ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
+						>> DRM_ELD_VER_SHIFT;
+
+	if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
+		dev_dbg(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver);
+		return -EINVAL;
+	}
+
+	mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
+		DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
+
+	if (mnl > ELD_MAX_MNL) {
+		dev_dbg(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl);
+		return -EINVAL;
+	}
+
 	pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER];
+
+	return 0;
 }
 
-static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
+static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
 {
 	struct hdac_ext_device *edev = pin->edev;
 	struct hdac_hdmi_priv *hdmi = edev->private_data;
 	struct hdac_hdmi_pcm *pcm;
-	int val;
-
-	pin->repoll_count = repoll;
+	int size;
 
-	pm_runtime_get_sync(&edev->hdac.dev);
-	val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0,
-					AC_VERB_GET_PIN_SENSE, 0);
+	mutex_lock(&hdmi->pin_mutex);
+	pin->eld.monitor_present = false;
 
-	dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n",
-						val, pin->nid);
+	size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1,
+				&pin->eld.monitor_present, pin->eld.eld_buffer,
+				ELD_MAX_SIZE);
 
+	if (size > 0) {
+		size = min(size, ELD_MAX_SIZE);
+		if (hdac_hdmi_parse_eld(edev, pin) < 0)
+			size = -EINVAL;
+	}
 
-	mutex_lock(&hdmi->pin_mutex);
-	pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE);
-	pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV);
+	if (size > 0) {
+		pin->eld.eld_valid = true;
+		pin->eld.eld_size = size;
+	} else {
+		pin->eld.eld_valid = false;
+		pin->eld.eld_size = 0;
+	}
 
 	pcm = hdac_hdmi_get_pcm(edev, pin);
 
@@ -1106,66 +1061,23 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
 		}
 
 		mutex_unlock(&hdmi->pin_mutex);
-		goto put_hdac_device;
+		return;
 	}
 
 	if (pin->eld.monitor_present && pin->eld.eld_valid) {
-		/* TODO: use i915 component for reading ELD later */
-		if (hdac_hdmi_get_eld(&edev->hdac, pin->nid,
-				pin->eld.eld_buffer,
-				&pin->eld.eld_size) == 0) {
-
-			if (pcm) {
-				dev_dbg(&edev->hdac.dev,
-					"jack report for pcm=%d\n",
-					pcm->pcm_id);
-
-				snd_jack_report(pcm->jack, SND_JACK_AVOUT);
-			}
-			hdac_hdmi_parse_eld(edev, pin);
-
-			print_hex_dump_debug("ELD: ",
-					DUMP_PREFIX_OFFSET, 16, 1,
-					pin->eld.eld_buffer, pin->eld.eld_size,
-					true);
-		} else {
-			pin->eld.monitor_present = false;
-			pin->eld.eld_valid = false;
-
-			if (pcm) {
-				dev_dbg(&edev->hdac.dev,
-					"jack report for pcm=%d\n",
-					pcm->pcm_id);
+		if (pcm) {
+			dev_dbg(&edev->hdac.dev,
+				"jack report for pcm=%d\n",
+				pcm->pcm_id);
 
-				snd_jack_report(pcm->jack, 0);
-			}
+			snd_jack_report(pcm->jack, SND_JACK_AVOUT);
 		}
+
+		print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
+			  pin->eld.eld_buffer, pin->eld.eld_size, false);
 	}
 
 	mutex_unlock(&hdmi->pin_mutex);
-
-	/*
-	 * Sometimes the pin_sense may present invalid monitor
-	 * present and eld_valid. If ELD data is not valid, loop few
-	 * more times to get correct pin sense and valid ELD.
-	 */
-	if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll)
-		schedule_delayed_work(&pin->work, msecs_to_jiffies(300));
-
-put_hdac_device:
-	pm_runtime_put_sync(&edev->hdac.dev);
-}
-
-static void hdac_hdmi_repoll_eld(struct work_struct *work)
-{
-	struct hdac_hdmi_pin *pin =
-		container_of(to_delayed_work(work), struct hdac_hdmi_pin, work);
-
-	/* picked from legacy HDA driver */
-	if (pin->repoll_count++ > 6)
-		pin->repoll_count = 0;
-
-	hdac_hdmi_present_sense(pin, pin->repoll_count);
 }
 
 static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
@@ -1184,7 +1096,6 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
 
 	pin->edev = edev;
 	mutex_init(&pin->lock);
-	INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld);
 
 	return 0;
 }
@@ -1395,7 +1306,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port)
 
 	list_for_each_entry(pin, &hdmi->pin_list, head) {
 		if (pin->nid == pin_nid)
-			hdac_hdmi_present_sense(pin, 1);
+			hdac_hdmi_present_sense(pin);
 	}
 }
 
@@ -1496,7 +1407,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
 	}
 
 	list_for_each_entry(pin, &hdmi->pin_list, head)
-		hdac_hdmi_present_sense(pin, 1);
+		hdac_hdmi_present_sense(pin);
 
 	/* Imp: Store the card pointer in hda_codec */
 	edev->card = dapm->card->snd_card;
@@ -1561,7 +1472,7 @@ static void hdmi_codec_complete(struct device *dev)
 	 * all pins here.
 	 */
 	list_for_each_entry(pin, &hdmi->pin_list, head)
-		hdac_hdmi_present_sense(pin, 1);
+		hdac_hdmi_present_sense(pin);
 
 	pm_runtime_put_sync(&edev->hdac.dev);
 }
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Applied "ASoC: Intel: bxt: Add route change to da7219_max98357a machine" to the asoc tree
  2016-09-20 13:46 ` [RFC 07/16] ASoC: Intel: Skylake: Add route change to da7219_max98357a machine jeeja.kp
@ 2017-02-04 12:12   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2017-02-04 12:12 UTC (permalink / raw)
  To: Jeeja KP; +Cc: tiwai, patches.audio, alsa-devel, broonie, liam.r.girdwood

The patch

   ASoC: Intel: bxt: Add route change to da7219_max98357a machine

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 6d707a74a79c7698bd3b797586c2f6ae55eae56c Mon Sep 17 00:00:00 2001
From: Jeeja KP <jeeja.kp@intel.com>
Date: Tue, 24 Jan 2017 21:49:13 +0530
Subject: [PATCH] ASoC: Intel: bxt: Add route change to da7219_max98357a
 machine

To support MST moved pin to port, this changes the routes based on
port. So change the route in bxt_da7219_max98357a machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/bxt_da7219_max98357a.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c
index 02439ace3519..876d82d4a39e 100644
--- a/sound/soc/intel/boards/bxt_da7219_max98357a.c
+++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c
@@ -84,9 +84,9 @@ static const struct snd_soc_dapm_route broxton_map[] = {
 	{"codec0_in", NULL, "ssp1 Rx"},
 	{"ssp1 Rx", NULL, "Capture"},
 
-	{"HDMI1", NULL, "hif5 Output"},
-	{"HDMI2", NULL, "hif6 Output"},
-	{"HDMI3", NULL, "hif7 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI2", NULL, "hif7-0 Output"},
 
 	{"hifi3", NULL, "iDisp3 Tx"},
 	{"iDisp3 Tx", NULL, "iDisp3_out"},
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Applied "ASoC: Intel: Skylake: Add route change to rt286 machine" to the asoc tree
  2016-09-20 13:46 ` [RFC 03/16] ASoC: Intel: Skylake: Add route change to rt286 machine jeeja.kp
@ 2017-02-04 12:12   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2017-02-04 12:12 UTC (permalink / raw)
  To: Jeeja KP; +Cc: tiwai, patches.audio, alsa-devel, broonie, liam.r.girdwood

The patch

   ASoC: Intel: Skylake: Add route change to rt286 machine

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 111c2ae1fb46f66e1acd8b077377919954d6aa64 Mon Sep 17 00:00:00 2001
From: Jeeja KP <jeeja.kp@intel.com>
Date: Tue, 24 Jan 2017 21:49:09 +0530
Subject: [PATCH] ASoC: Intel: Skylake: Add route change to rt286 machine

To support MST moved pin to port, this changes the routes based on
port. So change the route in skl_rt286 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/skl_rt286.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c
index dc5c3611a6ff..5e56af3a6ee3 100644
--- a/sound/soc/intel/boards/skl_rt286.c
+++ b/sound/soc/intel/boards/skl_rt286.c
@@ -94,9 +94,9 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
 	{"DMIC1 Pin", NULL, "DMIC2"},
 	{"DMic", NULL, "SoC DMIC"},
 
-	{"HDMI1", NULL, "hif5 Output"},
-	{"HDMI2", NULL, "hif6 Output"},
-	{"HDMI3", NULL, "hif7 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI3", NULL, "hif7-0 Output"},
 
 	/* CODEC BE connections */
 	{ "AIF1 Playback", NULL, "ssp0 Tx"},
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Applied "ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine" to the asoc tree
  2016-09-20 13:46 ` [RFC 05/16] ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine jeeja.kp
@ 2017-02-08 18:34   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2017-02-08 18:34 UTC (permalink / raw)
  To: Jeeja KP; +Cc: tiwai, patches.audio, alsa-devel, broonie, liam.r.girdwood

The patch

   ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 8d13640f6b9f1f99035d7078b3cd4002e9af5d9c Mon Sep 17 00:00:00 2001
From: Jeeja KP <jeeja.kp@intel.com>
Date: Mon, 6 Feb 2017 12:09:16 +0530
Subject: [PATCH] ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567
 machine

To support MST moved pin to port, this changes the routes based on
port. So change the route in nau88l25_ssm4567 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
index 8ab865ee0cad..41117bc51450 100644
--- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
+++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
@@ -115,8 +115,8 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
 	SND_SOC_DAPM_SPK("Left Speaker", NULL),
 	SND_SOC_DAPM_SPK("Right Speaker", NULL),
 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-	SND_SOC_DAPM_SPK("DP", NULL),
-	SND_SOC_DAPM_SPK("HDMI", NULL),
+	SND_SOC_DAPM_SPK("DP1", NULL),
+	SND_SOC_DAPM_SPK("DP2", NULL),
 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMD),
@@ -135,8 +135,9 @@ static const struct snd_soc_dapm_route skylake_map[] = {
 	{"MIC", NULL, "Headset Mic"},
 	{"DMic", NULL, "SoC DMIC"},
 
-	{"HDMI", NULL, "hif5 Output"},
-	{"DP", NULL, "hif6 Output"},
+	{"DP1", NULL, "hif5-0 Output"},
+	{"DP2", NULL, "hif6-0 Output"},
+
 	/* CODEC BE connections */
 	{ "Left Playback", NULL, "ssp0 Tx"},
 	{ "Right Playback", NULL, "ssp0 Tx"},
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Applied "ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine" to the asoc tree
  2016-09-20 13:46 ` [RFC 04/16] ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine jeeja.kp
@ 2017-02-08 18:34   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2017-02-08 18:34 UTC (permalink / raw)
  To: Jeeja KP; +Cc: tiwai, patches.audio, alsa-devel, broonie, liam.r.girdwood

The patch

   ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From b0aad231bd1edd297a3e60acf26f9dceff1937a7 Mon Sep 17 00:00:00 2001
From: Jeeja KP <jeeja.kp@intel.com>
Date: Mon, 6 Feb 2017 12:09:15 +0530
Subject: [PATCH] ASoC: Intel: Skylake: Add route change to nau88l25_max98357a
 machine

To support MST moved pin to port, this changes the routes based on
port. So change the route in nau88l25_max98357a machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/skl_nau88l25_max98357a.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
index fddd1cd12f13..bb4196867752 100644
--- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c
+++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
@@ -111,8 +111,8 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_SPK("Spk", NULL),
 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-	SND_SOC_DAPM_SPK("DP", NULL),
-	SND_SOC_DAPM_SPK("HDMI", NULL),
+	SND_SOC_DAPM_SPK("DP1", NULL),
+	SND_SOC_DAPM_SPK("DP2", NULL),
 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMD),
@@ -130,8 +130,8 @@ static const struct snd_soc_dapm_route skylake_map[] = {
 	{ "MIC", NULL, "Headset Mic" },
 	{ "DMic", NULL, "SoC DMIC" },
 
-	{"HDMI", NULL, "hif5 Output"},
-	{"DP", NULL, "hif6 Output"},
+	{"DP1", NULL, "hif5-0 Output"},
+	{"DP2", NULL, "hif6-0 Output"},
 
 	/* CODEC BE connections */
 	{ "HiFi Playback", NULL, "ssp0 Tx" },
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Applied "ASoC: Intel: bxt: Add route change to rt298 machine" to the asoc tree
  2016-09-20 13:46 ` [RFC 06/16] ASoC: Intel: Skylake: Add route change to rt298 machine jeeja.kp
@ 2017-02-08 18:34   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2017-02-08 18:34 UTC (permalink / raw)
  To: Jeeja KP; +Cc: tiwai, patches.audio, alsa-devel, broonie, liam.r.girdwood

The patch

   ASoC: Intel: bxt: Add route change to rt298 machine

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From eaba31035aa925b04d7d63120283e40a0e96e4a8 Mon Sep 17 00:00:00 2001
From: Jeeja KP <jeeja.kp@intel.com>
Date: Mon, 6 Feb 2017 12:09:17 +0530
Subject: [PATCH] ASoC: Intel: bxt: Add route change to rt298 machine

To support MST moved pin to port, this changes the routes based on
port. So change the route in bxt_rt298 machine.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/bxt_rt298.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c
index bc9ee0975073..09be868833d1 100644
--- a/sound/soc/intel/boards/bxt_rt298.c
+++ b/sound/soc/intel/boards/bxt_rt298.c
@@ -92,9 +92,9 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
 	{"DMIC1 Pin", NULL, "DMIC2"},
 	{"DMic", NULL, "SoC DMIC"},
 
-	{"HDMI1", NULL, "hif5 Output"},
-	{"HDMI2", NULL, "hif6 Output"},
-	{"HDMI3", NULL, "hif7 Output"},
+	{"HDMI1", NULL, "hif5-0 Output"},
+	{"HDMI2", NULL, "hif6-0 Output"},
+	{"HDMI2", NULL, "hif7-0 Output"},
 
 	/* CODEC BE connections */
 	{ "AIF1 Playback", NULL, "ssp5 Tx"},
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2017-02-08 18:34 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-20 13:46 [RFC 00/16] ASoC: hdac_hdmi: Add Support to Enable MST Audio jeeja.kp
2016-09-20 13:46 ` [RFC 01/16] ASoC: hdac_hdmi: use audio component framework to read ELD jeeja.kp
2016-09-25  5:58   ` Applied "ASoC: hdac_hdmi: use audio component framework to read ELD" to the asoc tree Mark Brown
2016-09-20 13:46 ` [RFC 02/16] ASoC: hdac_hdmi: Begin to add support for DP Multi-stream Audio jeeja.kp
2016-09-20 13:46 ` [RFC 03/16] ASoC: Intel: Skylake: Add route change to rt286 machine jeeja.kp
2017-02-04 12:12   ` Applied "ASoC: Intel: Skylake: Add route change to rt286 machine" to the asoc tree Mark Brown
2016-09-20 13:46 ` [RFC 04/16] ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine jeeja.kp
2017-02-08 18:34   ` Applied "ASoC: Intel: Skylake: Add route change to nau88l25_max98357a machine" to the asoc tree Mark Brown
2016-09-20 13:46 ` [RFC 05/16] ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine jeeja.kp
2017-02-08 18:34   ` Applied "ASoC: Intel: Skylake: Add route change to nau88l25_ssm4567 machine" to the asoc tree Mark Brown
2016-09-20 13:46 ` [RFC 06/16] ASoC: Intel: Skylake: Add route change to rt298 machine jeeja.kp
2017-02-08 18:34   ` Applied "ASoC: Intel: bxt: Add route change to rt298 machine" to the asoc tree Mark Brown
2016-09-20 13:46 ` [RFC 07/16] ASoC: Intel: Skylake: Add route change to da7219_max98357a machine jeeja.kp
2017-02-04 12:12   ` Applied "ASoC: Intel: bxt: Add route change to da7219_max98357a machine" to the asoc tree Mark Brown
2016-09-20 13:46 ` [RFC 08/16] ASoC: hdac_hdmi: Add support to handle MST capable pin jeeja.kp
2016-09-20 13:46 ` [RFC 09/16] ASoC: hdac_hdmi: Add MST verb support jeeja.kp
2016-09-20 13:46 ` [RFC 10/16] ASoc: hdac_hdmi: Configure pin verbs for MST jeeja.kp
2016-09-20 13:46 ` [RFC 11/16] ASoC: hdac_hdmi: Add support to handle Multiple Port to same PCM jeeja.kp
2016-09-20 13:46 ` [RFC 12/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt286 machine jeeja.kp
2016-09-20 13:46 ` [RFC 13/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_max machine jeeja.kp
2016-09-20 13:46 ` [RFC 14/16] ASoC: Intel: Skylake: To support MST, add HDMI routes nau_ssm machine jeeja.kp
2016-09-20 13:46 ` [RFC 15/16] ASoC: Intel: Skylake: To support MST, add HDMI routes rt298 machine jeeja.kp
2016-09-20 13:46 ` [RFC 16/16] ASoC: Intel: Skylake: To support MST, add HDMI routes da7219_max machine jeeja.kp

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.