Browse Source

Merge "asoc: add multi stream support for display port"

qctecmdr 5 years ago
parent
commit
49ac33f0a1
5 changed files with 206 additions and 65 deletions
  1. 103 49
      asoc/codecs/msm_hdmi_codec_rx.c
  2. 18 2
      asoc/kona.c
  3. 80 13
      asoc/msm-dai-q6-hdmi-v2.c
  4. 4 1
      asoc/msm-dai-q6-v2.h
  5. 1 0
      asoc/msm-pcm-routing-v2.c

+ 103 - 49
asoc/codecs/msm_hdmi_codec_rx.c

@@ -43,8 +43,12 @@ enum {
 	DP_STREAM_MAX,
 };
 
+/*
+ * Dai id cannot be zero, if component has more than one dai and dai id
+ * is used to differentiate between them
+ */
 enum {
-	DP_DAI1 = 0,
+	DP_DAI1 = 1,
 	DP_DAI2,
 	HDMI_DAI,
 	DP_DAI_MAX,
@@ -54,16 +58,16 @@ static const char *const ext_disp_audio_type_text[] = {"None", "HDMI", "DP"};
 static const char *const ext_disp_audio_ack_text[] = {"Disconnect",  "Connect",
 						      "Ack_Enable"};
 
-SOC_EXT_DISP_AUDIO_TYPE(0);
-SOC_EXT_DISP_AUDIO_ACK_STATE(0);
 SOC_EXT_DISP_AUDIO_TYPE(1);
 SOC_EXT_DISP_AUDIO_ACK_STATE(1);
+SOC_EXT_DISP_AUDIO_TYPE(2);
+SOC_EXT_DISP_AUDIO_ACK_STATE(2);
 
 struct msm_ext_disp_audio_codec_rx_data {
 	struct platform_device *ext_disp_core_pdev;
 	struct msm_ext_disp_audio_codec_ops ext_disp_ops;
-	int cable_status;
 	struct mutex dp_ops_lock;
+	int cable_status[DP_DAI_MAX];
 	int stream[DP_DAI_MAX];
 	int ctl[DP_DAI_MAX];
 };
@@ -80,25 +84,25 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
 	int dai_id = kcontrol->private_value;
 
 	codec_data = snd_soc_component_get_drvdata(component);
-
 	if (!codec_data) {
 		dev_err(component->dev, "%s: codec_data is NULL\n", __func__);
 		return -EINVAL;
 	}
 
+	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
+		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
+
+	mutex_lock(&codec_data->dp_ops_lock);
+	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
 	if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
 		dev_dbg(component->dev, "%s: get_audio_edid_blk() is NULL\n",
 			__func__);
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 		uinfo->count = 0;
-		return 0;
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
 	}
 
-	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
-		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
-
-	mutex_lock(&codec_data->dp_ops_lock);
-	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
 	rc = codec_data->ext_disp_ops.get_audio_edid_blk(
 				codec_data->ext_disp_core_pdev, &edid_blk);
 	mutex_unlock(&codec_data->dp_ops_lock);
@@ -124,8 +128,8 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
 	int dai_id = kcontrol->private_value;
 
 	codec_data = snd_soc_component_get_drvdata(component);
-	if (!codec_data || !codec_data->ext_disp_ops.get_audio_edid_blk) {
-		dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
+	if (!codec_data) {
+		dev_err(component->dev, "%s: codec_data is NULL\n",
 			__func__);
 		return -EINVAL;
 	}
@@ -135,6 +139,13 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
+		dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
+	}
+
 	rc = codec_data->ext_disp_ops.get_audio_edid_blk(
 			codec_data->ext_disp_core_pdev, &edid_blk);
 	mutex_unlock(&codec_data->dp_ops_lock);
@@ -177,10 +188,8 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
 	int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
 
 	codec_data = snd_soc_component_get_drvdata(component);
-	if (!codec_data ||
-	    !codec_data->ext_disp_ops.get_audio_edid_blk ||
-	    !codec_data->ext_disp_ops.get_intf_id) {
-		dev_err(component->dev, "%s: codec_data, get_audio_edid_blk() or get_intf_id is NULL\n",
+	if (!codec_data) {
+		dev_err(component->dev, "%s: codec_data is NULL\n",
 			__func__);
 		return -EINVAL;
 	}
@@ -190,6 +199,15 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
+	    !codec_data->ext_disp_ops.get_intf_id) {
+		dev_err(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
+			__func__);
+		rc = -EINVAL;
+		goto cable_err;
+	}
+
 	cable_state = codec_data->ext_disp_ops.cable_status(
 				   codec_data->ext_disp_core_pdev, 1);
 	if (cable_state < 0) {
@@ -199,7 +217,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
 		goto cable_err;
 	}
 
-	codec_data->cable_status = cable_state;
+	codec_data->cable_status[dai_id] = cable_state;
 	if (cable_state == EXT_DISPLAY_CABLE_DISCONNECT) {
 		dev_err(component->dev, "%s: Display cable disconnected\n",
 			__func__);
@@ -254,18 +272,27 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
 	int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
 
 	codec_data = snd_soc_component_get_drvdata(component);
-	if (!codec_data ||
-	    !codec_data->ext_disp_ops.acknowledge) {
+	if (!codec_data) {
 		dev_err(component->dev,
-			"%s: codec_data or ops acknowledge() is NULL\n",
+			"%s: codec_data is NULL\n",
 			__func__);
-		rc = -EINVAL;
-		goto done;
+		return -EINVAL;
 	}
 
 	dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
 		codec_data->ctl[dai_id], codec_data->stream[dai_id]);
 
+	mutex_lock(&codec_data->dp_ops_lock);
+	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+
+	if (!codec_data->ext_disp_ops.acknowledge) {
+		dev_err(component->dev,
+			"%s: codec_data ops acknowledge() is NULL\n",
+			__func__);
+		rc = -EINVAL;
+		goto err;
+	}
+
 	switch (ucontrol->value.enumerated.item[0]) {
 	case 0:
 		ack_state = AUD_EXT_DISP_ACK_DISCONNECT;
@@ -281,13 +308,11 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
 		dev_err(component->dev,
 			"%s: invalid value %d for mixer ctl\n",
 			__func__, ucontrol->value.enumerated.item[0]);
-		goto done;
+		goto err;
 	}
 	dev_dbg(component->dev, "%s: control %d, ack set value 0x%x\n",
 		__func__, ucontrol->value.enumerated.item[0], ack_state);
 
-	mutex_lock(&codec_data->dp_ops_lock);
-	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
 	rc = codec_data->ext_disp_ops.acknowledge(
 			 codec_data->ext_disp_core_pdev, ack_state);
 	mutex_unlock(&codec_data->dp_ops_lock);
@@ -295,8 +320,10 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
 		dev_err(component->dev, "%s: error from acknowledge(), err:%d\n",
 			__func__, rc);
 	}
+	return rc;
 
-done:
+err:
+	mutex_unlock(&codec_data->dp_ops_lock);
 	return rc;
 }
 
@@ -407,16 +434,16 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
 		.private_value = DP_DAI2,
 	},
 	SOC_ENUM_EXT("External Display Type",
-		     ext_disp_audio_type0,
+		     ext_disp_audio_type1,
 		     msm_ext_disp_audio_type_get, NULL),
 	SOC_ENUM_EXT("External Display1 Type",
-		     ext_disp_audio_type1,
+		     ext_disp_audio_type2,
 		     msm_ext_disp_audio_type_get, NULL),
 	SOC_ENUM_EXT("External Display Audio Ack",
-		     ext_disp_audio_ack_state0,
+		     ext_disp_audio_ack_state1,
 		     NULL, msm_ext_disp_audio_ack_set),
 	SOC_ENUM_EXT("External Display1 Audio Ack",
-		     ext_disp_audio_ack_state1,
+		     ext_disp_audio_ack_state2,
 		     NULL, msm_ext_disp_audio_ack_set),
 
 	SOC_SINGLE_MULTI_EXT("External Display Audio Device",
@@ -438,8 +465,8 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
 	struct msm_ext_disp_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->component->dev);
 
-	if (!codec_data || !codec_data->ext_disp_ops.cable_status) {
-		dev_err(dai->dev, "%s() codec_data or cable_status is null\n",
+	if (!codec_data) {
+		dev_err(dai->dev, "%s() codec_data is null\n",
 			__func__);
 		return -EINVAL;
 	}
@@ -450,19 +477,27 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
-	codec_data->cable_status =
+
+	if (!codec_data->ext_disp_ops.cable_status) {
+		dev_err(dai->dev, "%s() cable_status is null\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
+	}
+
+	codec_data->cable_status[dai->id] =
 		codec_data->ext_disp_ops.cable_status(
 		codec_data->ext_disp_core_pdev, 1);
 	mutex_unlock(&codec_data->dp_ops_lock);
-	if (codec_data->cable_status < 0) {
+	if (codec_data->cable_status[dai->id] < 0) {
 		dev_err(dai->dev,
 			"%s() ext disp core is not ready (ret val = %d)\n",
-			__func__, codec_data->cable_status);
-		ret = codec_data->cable_status;
-	} else if (!codec_data->cable_status) {
+			__func__, codec_data->cable_status[dai->id]);
+		ret = codec_data->cable_status[dai->id];
+	} else if (!codec_data->cable_status[dai->id]) {
 		dev_err(dai->dev,
 			"%s() ext disp cable is not connected (ret val = %d)\n",
-			__func__, codec_data->cable_status);
+			__func__, codec_data->cable_status[dai->id]);
 		ret = -ENODEV;
 	}
 
@@ -485,8 +520,8 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
 	struct msm_ext_disp_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->component->dev);
 
-	if (!codec_data || !codec_data->ext_disp_ops.audio_info_setup) {
-		dev_err(dai->dev, "%s: codec_data or audio_info_setup is null\n",
+	if (!codec_data) {
+		dev_err(dai->dev, "%s() codec_data is null\n",
 			__func__);
 		return -EINVAL;
 	}
@@ -495,15 +530,26 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
 		__func__,
 		codec_data->ctl[dai->id], codec_data->stream[dai->id]);
 
-	if (codec_data->cable_status < 0) {
+	mutex_lock(&codec_data->dp_ops_lock);
+	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+
+	if (!codec_data->ext_disp_ops.audio_info_setup) {
+		dev_err(dai->dev, "%s: audio_info_setup is null\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&codec_data->dp_ops_lock);
+
+	if (codec_data->cable_status[dai->id] < 0) {
 		dev_err_ratelimited(dai->dev,
 			"%s() ext disp core is not ready (ret val = %d)\n",
-			__func__, codec_data->cable_status);
-		return codec_data->cable_status;
-	} else if (!codec_data->cable_status) {
+			__func__, codec_data->cable_status[dai->id]);
+		return codec_data->cable_status[dai->id];
+	} else if (!codec_data->cable_status[dai->id]) {
 		dev_err_ratelimited(dai->dev,
 			"%s() ext disp cable is not connected (ret val = %d)\n",
-			__func__, codec_data->cable_status);
+			__func__, codec_data->cable_status[dai->id]);
 		return -ENODEV;
 	}
 
@@ -576,9 +622,8 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
 	struct msm_ext_disp_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->component->dev);
 
-	if (!codec_data || !codec_data->ext_disp_ops.teardown_done ||
-	    !codec_data->ext_disp_ops.cable_status) {
-		dev_err(dai->dev, "%s: codec data or teardown_done or cable_status is null\n",
+	if (!codec_data) {
+		dev_err(dai->dev, "%s() codec_data is null\n",
 			__func__);
 		return;
 	}
@@ -589,6 +634,15 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+
+	if (!codec_data->ext_disp_ops.teardown_done ||
+	    !codec_data->ext_disp_ops.cable_status) {
+		dev_err(dai->dev, "%s: teardown_done or cable_status is null\n",
+			__func__);
+		mutex_unlock(&codec_data->dp_ops_lock);
+		return;
+	}
+
 	rc = codec_data->ext_disp_ops.cable_status(
 			codec_data->ext_disp_core_pdev, 0);
 	if (rc < 0) {

+ 18 - 2
asoc/kona.c

@@ -178,6 +178,7 @@ struct tdm_port {
 
 enum {
 	EXT_DISP_RX_IDX_DP = 0,
+	EXT_DISP_RX_IDX_DP1,
 	EXT_DISP_RX_IDX_MAX,
 };
 
@@ -210,6 +211,7 @@ static struct dev_config slim_tx_cfg[] = {
 /* Default configuration of external display BE */
 static struct dev_config ext_disp_rx_cfg[] = {
 	[EXT_DISP_RX_IDX_DP] =   {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[EXT_DISP_RX_IDX_DP1] =   {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
 };
 
 static struct dev_config usb_rx_cfg = {
@@ -1135,6 +1137,9 @@ static int ext_disp_get_port_idx(struct snd_kcontrol *kcontrol)
 	if (strnstr(kcontrol->id.name, "Display Port RX",
 		    sizeof("Display Port RX"))) {
 		idx = EXT_DISP_RX_IDX_DP;
+	} else if (strnstr(kcontrol->id.name, "Display Port1 RX",
+		    sizeof("Display Port1 RX"))) {
+		idx = EXT_DISP_RX_IDX_DP1;
 	} else {
 		pr_err("%s: unsupported BE: %s\n",
 			__func__, kcontrol->id.name);
@@ -3658,6 +3663,13 @@ static const struct snd_kcontrol_new msm_common_snd_controls[] = {
 	SOC_ENUM_EXT("Display Port RX SampleRate", ext_disp_rx_sample_rate,
 			ext_disp_rx_sample_rate_get,
 			ext_disp_rx_sample_rate_put),
+	SOC_ENUM_EXT("Display Port1 RX Channels", ext_disp_rx_chs,
+			ext_disp_rx_ch_get, ext_disp_rx_ch_put),
+	SOC_ENUM_EXT("Display Port1 RX Bit Format", ext_disp_rx_format,
+			ext_disp_rx_format_get, ext_disp_rx_format_put),
+	SOC_ENUM_EXT("Display Port1 RX SampleRate", ext_disp_rx_sample_rate,
+			ext_disp_rx_sample_rate_get,
+			ext_disp_rx_sample_rate_put),
 	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
 			msm_bt_sample_rate_get,
 			msm_bt_sample_rate_put),
@@ -3694,6 +3706,9 @@ static int msm_ext_disp_get_idx_from_beid(int32_t be_id)
 	case MSM_BACKEND_DAI_DISPLAY_PORT_RX:
 		idx = EXT_DISP_RX_IDX_DP;
 		break;
+	case MSM_BACKEND_DAI_DISPLAY_PORT_RX_1:
+		idx = EXT_DISP_RX_IDX_DP1;
+		break;
 	default:
 		pr_err("%s: Incorrect ext_disp BE id %d\n", __func__, be_id);
 		idx = -EINVAL;
@@ -3756,6 +3771,7 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 		break;
 
 	case MSM_BACKEND_DAI_DISPLAY_PORT_RX:
+	case MSM_BACKEND_DAI_DISPLAY_PORT_RX_1:
 		idx = msm_ext_disp_get_idx_from_beid(dai_link->id);
 		if (idx < 0) {
 			pr_err("%s: Incorrect ext disp idx %d\n",
@@ -6106,7 +6122,7 @@ static struct snd_soc_dai_link ext_disp_be_dai_link[] = {
 	{
 		.name = LPASS_BE_DISPLAY_PORT,
 		.stream_name = "Display Port Playback",
-		.cpu_dai_name = "msm-dai-q6-dp.24608",
+		.cpu_dai_name = "msm-dai-q6-dp.0",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-ext-disp-audio-codec-rx",
 		.codec_dai_name = "msm_dp_audio_codec_rx_dai",
@@ -6121,7 +6137,7 @@ static struct snd_soc_dai_link ext_disp_be_dai_link[] = {
 	{
 		.name = LPASS_BE_DISPLAY_PORT1,
 		.stream_name = "Display Port1 Playback",
-		.cpu_dai_name = "msm-dai-q6-dp.24608",
+		.cpu_dai_name = "msm-dai-q6-dp.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-ext-disp-audio-codec-rx",
 		.codec_dai_name = "msm_dp_audio_codec_rx1_dai",

+ 80 - 13
asoc/msm-dai-q6-hdmi-v2.c

@@ -51,6 +51,15 @@ struct msm_dai_q6_hdmi_dai_data {
 	union afe_port_config port_config;
 };
 
+static int get_port_id(int dai_id)
+{
+	/* Currently, display devices share a common AFE port */
+	if (dai_id != HDMI_RX)
+		return DISPLAY_PORT_RX;
+
+	return dai_id;
+}
+
 static int msm_dai_q6_ext_disp_format_put(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_value *ucontrol)
 {
@@ -198,10 +207,10 @@ static int msm_dai_q6_ext_disp_drift_get(struct snd_kcontrol *kcontrol,
 	}
 
 	memset(&timing_stats, 0, sizeof(struct afe_param_id_dev_timing_stats));
-	ret = afe_get_av_dev_drift(&timing_stats, dai->id);
+	ret = afe_get_av_dev_drift(&timing_stats, get_port_id(dai->id));
 	if (ret) {
 		pr_err("%s: Error getting AFE Drift for port %d, err=%d\n",
-			__func__, dai->id, ret);
+			__func__, get_port_id(dai->id), ret);
 
 		ret = -EINVAL;
 		goto done;
@@ -249,6 +258,24 @@ static const struct snd_kcontrol_new display_port_config_controls[] = {
 		.info	= msm_dai_q6_ext_disp_drift_info,
 		.get	= msm_dai_q6_ext_disp_drift_get,
 	},
+	SOC_ENUM_EXT("Display Port1 RX Format", hdmi_config_enum[0],
+				 msm_dai_q6_ext_disp_format_get,
+				 msm_dai_q6_ext_disp_format_put),
+	SOC_SINGLE_MULTI_EXT("Display Port1 RX CA", SND_SOC_NOPM, 0,
+				 HDMI_RX_CA_MAX, 0, 1,
+				 msm_dai_q6_ext_disp_ca_get,
+				 msm_dai_q6_ext_disp_ca_put),
+	SOC_SINGLE_MULTI_EXT("Display Port1 RX DEVICE IDX", SND_SOC_NOPM, 0,
+				 1, 0, 2,
+				 msm_dai_q6_ext_disp_device_idx_get,
+				 msm_dai_q6_ext_disp_device_idx_put),
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface	= SNDRV_CTL_ELEM_IFACE_PCM,
+		.name	= "DISPLAY_PORT1 DRIFT",
+		.info	= msm_dai_q6_ext_disp_drift_info,
+		.get	= msm_dai_q6_ext_disp_drift_get,
+	},
 };
 
 /* Current implementation assumes hw_param is called once
@@ -329,7 +356,7 @@ static void msm_dai_q6_hdmi_shutdown(struct snd_pcm_substream *substream,
 		return;
 	}
 
-	rc = afe_close(dai->id); /* can block */
+	rc = afe_close(get_port_id(dai->id)); /* can block */
 	if (rc < 0)
 		dev_err(dai->dev, "fail to close AFE port\n");
 
@@ -351,8 +378,7 @@ static int msm_dai_q6_hdmi_prepare(struct snd_pcm_substream *substream,
 							      dai_data->ca.ca;
 
 	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-
-		rc = afe_set_display_stream(dai->id, dai_data->stream_idx,
+		rc = afe_set_display_stream(get_port_id(dai->id), dai_data->stream_idx,
 						dai_data->ctl_idx);
 		if (rc < 0) {
 			dev_err(dai->dev, "fail to set AFE ctl, stream ID params %x\n",
@@ -363,11 +389,11 @@ static int msm_dai_q6_hdmi_prepare(struct snd_pcm_substream *substream,
 			}
 		}
 
-		rc = afe_port_start(dai->id, &dai_data->port_config,
+		rc = afe_port_start(get_port_id(dai->id), &dai_data->port_config,
 				    dai_data->rate);
 		if (rc < 0)
 			dev_err(dai->dev, "fail to open AFE port %x\n",
-				dai->id);
+				get_port_id(dai->id));
 		else
 			set_bit(STATUS_PORT_STARTED,
 				dai_data->status_mask);
@@ -422,7 +448,7 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai)
 		kcontrol = &hdmi_config_controls[2];
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				 snd_ctl_new1(kcontrol, dai));
-	} else if (dai->driver->id == DISPLAY_PORT_RX) {
+	} else if (dai->driver->id == MSM_DISPLAY_PORT) {
 		kcontrol = &display_port_config_controls[0];
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				 snd_ctl_new1(kcontrol, dai_data));
@@ -438,6 +464,22 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai)
 		kcontrol = &display_port_config_controls[3];
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(kcontrol, dai));
+	} else if (dai->driver->id == MSM_DISPLAY_PORT1) {
+		kcontrol = &display_port_config_controls[4];
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(kcontrol, dai_data));
+
+		kcontrol = &display_port_config_controls[5];
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(kcontrol, dai_data));
+
+		kcontrol = &display_port_config_controls[6];
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(kcontrol, dai_data));
+
+		kcontrol = &display_port_config_controls[7];
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				snd_ctl_new1(kcontrol, dai));
 	} else {
 		dev_err(dai->dev, "%s: Invalid id:%d\n",
 			__func__, dai->driver->id);
@@ -482,7 +524,7 @@ static int msm_dai_q6_hdmi_dai_remove(struct snd_soc_dai *dai)
 
 	/* If AFE port is still up, close it */
 	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-		rc = afe_close(dai->id); /* can block */
+		rc = afe_close(get_port_id(dai->id)); /* can block */
 		if (rc < 0)
 			dev_err(dai->dev, "fail to close AFE port\n");
 
@@ -539,7 +581,28 @@ static struct snd_soc_dai_driver msm_dai_q6_display_port_rx_dai[] = {
 			.rate_min =     48000,
 		},
 		.ops = &msm_dai_q6_hdmi_ops,
-		.id = DISPLAY_PORT_RX,
+		.id = MSM_DISPLAY_PORT,
+		.probe = msm_dai_q6_hdmi_dai_probe,
+		.remove = msm_dai_q6_hdmi_dai_remove,
+	},
+	{
+		.playback = {
+			.stream_name = "Display Port1 Playback",
+			.aif_name = "DISPLAY_PORT1",
+			.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+				 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+				 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+				 SNDRV_PCM_RATE_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S24_3LE,
+			.channels_min = 2,
+			.channels_max = 8,
+			.rate_max =     192000,
+			.rate_min =     48000,
+		},
+		.ops = &msm_dai_q6_hdmi_ops,
+		.id = MSM_DISPLAY_PORT1,
 		.probe = msm_dai_q6_hdmi_dai_probe,
 		.remove = msm_dai_q6_hdmi_dai_remove,
 	},
@@ -573,11 +636,15 @@ static int msm_dai_q6_hdmi_dev_probe(struct platform_device *pdev)
 			&msm_dai_hdmi_q6_component,
 			&msm_dai_q6_hdmi_hdmi_rx_dai, 1);
 		break;
-	case DISPLAY_PORT_RX:
+	case MSM_DISPLAY_PORT:
+		rc = snd_soc_register_component(&pdev->dev,
+			&msm_dai_hdmi_q6_component,
+			&msm_dai_q6_display_port_rx_dai[0], 1);
+		break;
+	case MSM_DISPLAY_PORT1:
 		rc = snd_soc_register_component(&pdev->dev,
 			&msm_dai_hdmi_q6_component,
-			&msm_dai_q6_display_port_rx_dai[0],
-			ARRAY_SIZE(msm_dai_q6_display_port_rx_dai));
+			&msm_dai_q6_display_port_rx_dai[1], 1);
 		break;
 	default:
 		dev_err(&pdev->dev, "invalid device ID %d\n", pdev->id);

+ 4 - 1
asoc/msm-dai-q6-v2.h

@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 2019 The Linux Foundation. All rights reserved.
  */
 
 #ifndef __MSM_DAI_Q6_PDATA_H__
@@ -35,6 +35,9 @@
 #define MSM_MI2S_MIN MSM_PRIM_MI2S
 #define MSM_MI2S_MAX MSM_INT6_MI2S
 
+#define MSM_DISPLAY_PORT	0
+#define MSM_DISPLAY_PORT1	1
+
 struct msm_dai_auxpcm_config {
 	u16 mode;
 	u16 sync;

+ 1 - 0
asoc/msm-pcm-routing-v2.c

@@ -5459,6 +5459,7 @@ static const char *const ec_ref_rx[] = { "None", "SLIM_RX", "I2S_RX",
 	"QUAT_TDM_RX_0", "QUAT_TDM_RX_1", "QUAT_TDM_RX_2", "SLIM_6_RX",
 	"TERT_MI2S_RX", "QUAT_MI2S_RX", "TERT_TDM_TX_0", "USB_AUDIO_RX",
 	"INT0_MI2S_RX", "INT4_MI2S_RX", "INT3_MI2S_TX", "DISPLAY_PORT",
+	"DISPLAY_PORT1",
 	"WSA_CDC_DMA_RX_0", "WSA_CDC_DMA_RX_1",
 	"WSA_CDC_DMA_TX_0", "WSA_CDC_DMA_TX_1", "WSA_CDC_DMA_TX_2",
 	"SLIM_7_RX", "RX_CDC_DMA_RX_0", "RX_CDC_DMA_RX_1", "RX_CDC_DMA_RX_2",