hal: add multi stream support for display port

Add support to switch audio stream between multiple
display ports.

CRs-Fixed: 2504445
Change-Id: I6ff80d12ea92b83b765faaf93b94ced98ea10d35
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index c2e1349..8512a4e 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -216,7 +216,9 @@
 
 #define IS_BIT_SET(NUM, bitno) (NUM & (1 << bitno))
 
-#define EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE 0x30
+#define EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE      0x30
+#define EXT_DISPLAY_PLUG_STATUS_NOTIFY_CONNECT     0x01
+#define EXT_DISPLAY_PLUG_STATUS_NOTIFY_DISCONNECT  0x00
 
 static ssize_t update_sysfs_node(const char *path, const char *data, size_t len)
 {
@@ -276,12 +278,14 @@
     return -1;
 }
 
-static int update_ext_disp_sysfs_node(const struct audio_device *adev, int node_value)
+static int update_ext_disp_sysfs_node(const struct audio_device *adev,
+                                      int node_value, int controller, int stream)
 {
     char ext_disp_ack_path[80] = {0};
     char ext_disp_ack_value[3] = {0};
     int index, ret = -1;
-    int ext_disp_type = platform_get_ext_disp_type(adev->platform);
+    int ext_disp_type = platform_get_ext_disp_type_v2(adev->platform, controller,
+                                                      stream);
 
     if (ext_disp_type < 0) {
         ALOGE("%s, Unable to get the external display type, err:%d",
@@ -305,26 +309,47 @@
     return ret;
 }
 
-static int update_audio_ack_state(const struct audio_device *adev, int node_value)
+static int update_audio_ack_state(const struct audio_device *adev,
+                                  int node_value,
+                                  int controller,
+                                  int stream)
 {
-    const char *mixer_ctl_name = "External Display Audio Ack";
-    struct mixer_ctl *ctl;
     int ret = 0;
+    int ctl_index = 0;
+    struct mixer_ctl *ctl = NULL;
+    const char *ctl_prefix = "External Display";
+    const char *ctl_suffix = "Audio Ack";
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
 
+    ctl_index = platform_get_display_port_ctl_index(controller, stream);
+    if (-EINVAL == ctl_index) {
+        ALOGE("%s: Unknown controller/stream %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    if (0 == ctl_index)
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                 "%s %s", ctl_prefix, ctl_suffix);
+    else
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                 "%s%d %s", ctl_prefix, ctl_index, ctl_suffix);
+
+    ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     /* If no mixer command support, fall back to sysfs node approach */
     if (!ctl) {
         ALOGI("%s: could not get ctl for mixer cmd(%s), use sysfs node instead\n",
               __func__, mixer_ctl_name);
-        ret = update_ext_disp_sysfs_node(adev, node_value);
+        ret = update_ext_disp_sysfs_node(adev, node_value, controller, stream);
     } else {
         char *ack_str = NULL;
 
         if (node_value == EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE)
             ack_str = "Ack_Enable";
-        else if (node_value == 1)
+        else if (node_value == EXT_DISPLAY_PLUG_STATUS_NOTIFY_CONNECT)
             ack_str = "Connect";
-        else if (node_value == 0)
+        else if (node_value == EXT_DISPLAY_PLUG_STATUS_NOTIFY_DISCONNECT)
             ack_str = "Disconnect";
         else {
             ALOGE("%s: Invalid input parameter - 0x%x\n",
@@ -343,24 +368,32 @@
 static void audio_extn_ext_disp_set_parameters(const struct audio_device *adev,
                                                      struct str_parms *parms)
 {
+    int controller = 0;
+    int stream = 0;
     char value[32] = {0};
     static bool is_hdmi_sysfs_node_init = false;
 
     if (str_parms_get_str(parms, "connect", value, sizeof(value)) >= 0
             && (atoi(value) & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
         //params = "connect=1024" for external display connection.
+        platform_get_controller_stream_from_params(parms, &controller, &stream);
         if (is_hdmi_sysfs_node_init == false) {
             //check if this is different for dp and hdmi
             is_hdmi_sysfs_node_init = true;
-            update_audio_ack_state(adev, EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE);
+            update_audio_ack_state(adev,
+                                   EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE,
+                                   controller, stream);
         }
-        update_audio_ack_state(adev, 1);
+        update_audio_ack_state(adev, EXT_DISPLAY_PLUG_STATUS_NOTIFY_CONNECT,
+                               controller, stream);
     } else if(str_parms_get_str(parms, "disconnect", value, sizeof(value)) >= 0
             && (atoi(value) & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
         //params = "disconnect=1024" for external display disconnection.
-        update_audio_ack_state(adev, 0);
+        platform_get_controller_stream_from_params(parms, &controller, &stream);
+        update_audio_ack_state(adev, EXT_DISPLAY_PLUG_STATUS_NOTIFY_DISCONNECT,
+                               controller, stream);
         ALOGV("invalidate cached edid");
-        platform_invalidate_hdmi_config(adev->platform);
+        platform_invalidate_hdmi_config_v2(adev->platform, controller, stream);
     } else {
         // handle ext disp devices only
         return;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index ed1da44..91204a7 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -594,6 +594,12 @@
     EXT_DISPLAY_TYPE_HDMI,
     EXT_DISPLAY_TYPE_DP
 };
+
+// START: MST ==================================================
+#define MAX_CONTROLLERS 1
+#define MAX_STREAMS_PER_CONTROLLER 2
+// END: MST ==================================================
+
 // START: HDMI_PASSTHROUGH ==================================================
 /* Used to limit sample rate for TrueHD & EC3 */
 #define HDMI_PASSTHROUGH_MAX_SAMPLE_RATE 192000
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 21f68c1..bc2f159 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1836,12 +1836,16 @@
 static int read_hdmi_sink_caps(struct stream_out *out)
 {
     int ret = 0, i = 0, j = 0;
-    int channels = platform_edid_get_max_channels(out->dev->platform);
+    int channels = platform_edid_get_max_channels_v2(out->dev->platform,
+                                                     out->extconn.cs.controller,
+                                                     out->extconn.cs.stream);
 
     reset_hdmi_sink_caps(out);
 
     /* Cache ext disp type */
-    if (platform_get_ext_disp_type(adev->platform) <= 0) {
+    if (platform_get_ext_disp_type_v2(adev->platform,
+                                      out->extconn.cs.controller,
+                                      out->extconn.cs.stream <= 0)) {
         ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
         return -EINVAL;
     }
@@ -1867,7 +1871,9 @@
 
     // check channel format caps
     i = 0;
-    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
+    if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
+                                             out->extconn.cs.controller,
+                                             out->extconn.cs.stream)) {
         ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
         out->supported_formats[i++] = AUDIO_FORMAT_AC3;
         //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
@@ -1876,22 +1882,30 @@
         out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
     }
 
-    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
+    if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
+                                             out->extconn.cs.controller,
+                                             out->extconn.cs.stream)) {
         ALOGV(":%s HDMI supports TRUE HD format", __func__);
         out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
     }
 
-    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
+    if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
+                                             out->extconn.cs.controller,
+                                             out->extconn.cs.stream)) {
         ALOGV(":%s HDMI supports DTS format", __func__);
         out->supported_formats[i++] = AUDIO_FORMAT_DTS;
     }
 
-    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
+    if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
+                                             out->extconn.cs.controller,
+                                             out->extconn.cs.stream)) {
         ALOGV(":%s HDMI supports DTS HD format", __func__);
         out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
     }
 
-    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
+    if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
+                                             out->extconn.cs.controller,
+                                             out->extconn.cs.stream)) {
         ALOGV(":%s HDMI supports IEC61937 format", __func__);
         out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
     }
@@ -1900,7 +1914,9 @@
     // check sample rate caps
     i = 0;
     for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
-        if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
+        if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
+                                                      out->extconn.cs.controller,
+                                                      out->extconn.cs.stream)) {
             ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
             out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
         }
@@ -4431,6 +4447,8 @@
     struct str_parms *parms;
     char value[32];
     int ret = 0, val = 0, err;
+    int ext_controller = -1;
+    int ext_stream = -1;
     bool bypass_a2dp = false;
     bool reconfig = false;
     unsigned long service_interval = 0;
@@ -4440,6 +4458,17 @@
     parms = str_parms_create_str(kvpairs);
     if (!parms)
         goto error;
+
+    err = platform_get_controller_stream_from_params(parms, &ext_controller,
+                                                       &ext_stream);
+    if (err >= 0) {
+        out->extconn.cs.controller = ext_controller;
+        out->extconn.cs.stream = ext_stream;
+        ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
+              use_case_table[out->usecase], out->extconn.cs.controller,
+              out->extconn.cs.stream);
+    }
+
     err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
     if (err >= 0) {
         val = atoi(value);
@@ -4456,7 +4485,10 @@
         if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
                 (val == AUDIO_DEVICE_NONE) &&
                 !audio_extn_passthru_is_passthrough_stream(out) &&
-                (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
+                (platform_get_edid_info_v2(adev->platform,
+                                           out->extconn.cs.controller,
+                                           out->extconn.cs.stream) != 0)) {
+            out->extconn.cs.controller = out->extconn.cs.stream = -1;
             val = AUDIO_DEVICE_OUT_SPEAKER;
         }
         /*
@@ -4683,6 +4715,7 @@
             pthread_mutex_unlock(&out->lock);
         }
     }
+
     //end suspend, resume handling block
     str_parms_destroy(parms);
 error:
@@ -8116,6 +8149,7 @@
     bool a2dp_reconfig = false;
     struct listnode *node;
     struct audio_usecase *usecase = NULL;
+    int controller = -1, stream = -1;
 
     ALOGD("%s: enter: %s", __func__, kvpairs);
     parms = str_parms_create_str(kvpairs);
@@ -8243,11 +8277,13 @@
         if (audio_is_output_device(val) &&
             (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
             ALOGV("cache new ext disp type and edid");
-            ret = platform_get_ext_disp_type(adev->platform);
+            platform_get_controller_stream_from_params(parms, &controller, &stream);
+            platform_set_ext_display_device_v2(adev->platform, controller, stream);
+            ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
             if (ret < 0) {
                 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
             } else {
-                platform_cache_edid(adev->platform);
+                platform_cache_edid_v2(adev->platform, controller, stream);
             }
         } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
             /*
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 686d5a0..b1e61ad 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -435,6 +435,14 @@
 
     char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
     int car_audio_stream;
+
+    union {
+        char *addr;
+        struct {
+            int controller;
+            int stream;
+        } cs;
+    } extconn;
 };
 
 struct stream_in {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 64e9383..3094183 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -8610,3 +8610,93 @@
     *mic_count = actual_mic_count;
     return 0;
 }
+
+int platform_get_edid_info_v2(void *platform,
+                              int controller __unused,
+                              int stream __unused)
+{
+    return platform_get_edid_info(platform);
+}
+
+int platform_edid_get_max_channels_v2(void *platform,
+                                      int controller __unused,
+                                      int stream __unused)
+{
+    return platform_edid_get_max_channels(platform);
+}
+
+bool platform_is_edid_supported_format_v2(void *platform, int format,
+                                          int controller __unused,
+                                          int stream __unused)
+{
+    return platform_is_edid_supported_format(platform, format);
+}
+
+bool platform_is_edid_supported_sample_rate_v2(void *platform, int format,
+                                          int controller __unused,
+                                          int stream __unused)
+{
+    return platform_is_edid_supported_sample_rate(platform, format);
+}
+
+void platform_cache_edid_v2(void * platform,
+                            int controller __unused,
+                            int stream __unused)
+{
+    return platform_cache_edid(platform);
+}
+
+void platform_invalidate_hdmi_config_v2(void * platform,
+                                        int controller __unused,
+                                        int stream __unused)
+{
+    return platform_invalidate_hdmi_config(platform);
+}
+
+int platform_set_ext_display_device(void *platform, int controller, int stream)
+{
+    return -1;
+}
+
+int platform_get_controller_stream_from_params(struct str_parms *parms,
+                                               int *controller, int *stream);
+{
+    return -1;
+}
+
+int platform_get_ext_disp_type_v2(void *platform,
+                                  int controller __unused,
+                                  int stream __unused)
+{
+    return platform_get_ext_disp_type(platform);
+}
+
+int platform_set_edid_channels_configuration_v2(void *platform, int channels,
+                                             int backend_idx,
+                                             snd_device_t snd_device,
+                                             int controller __unused,
+                                             int stream __unused)
+{
+    return platform_set_edid_channels_configuration(platform, channels,
+                                                    backend_idx, snd_device);
+}
+
+int platform_set_channel_allocation_v2(void *platform,
+                                        int controller __unused,
+                                        int stream __unused)
+{
+    return platform_set_channel_allocation(platform);
+}
+
+int platform_set_hdmi_channels_v2(void *platform, int channel_count,
+                                  int controller __unused,
+                                  int stream __unused)
+{
+    return platform_set_hdmi_channels(platform, channel_count);
+}
+
+int platform_get_display_port_ctl_index(int controller __unused,
+                                        int stream __unused)
+{
+    return -EINVAL;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 07d3837..f6a3b1b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -260,6 +260,8 @@
     char     *bitwidth_mixer_ctl;
     char     *samplerate_mixer_ctl;
     char     *channels_mixer_ctl;
+    int      controller;
+    int      stream;
 } codec_backend_cfg_t;
 
 static native_audio_prop na_props = {0, 0, NATIVE_AUDIO_MODE_INVALID};
@@ -329,9 +331,11 @@
     void *hw_info;
     acdb_send_gain_dep_cal_t   acdb_send_gain_dep_cal;
     struct csd_data *csd;
-    void *edid_info;
-    bool edid_valid;
-    int ext_disp_type;
+    struct ext_disp_state {
+        void *edid_info;
+        bool valid;
+        int type;
+    } ext_disp[MAX_CONTROLLERS][MAX_STREAMS_PER_CONTROLLER];
     char ec_ref_mixer_path[MIXER_PATH_MAX_LENGTH];
     codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
     char codec_version[CODEC_VERSION_MAX_LENGTH];
@@ -523,7 +527,9 @@
     [SND_DEVICE_OUT_HDMI] = "hdmi",
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
     [SND_DEVICE_OUT_DISPLAY_PORT] = "display-port",
+    [SND_DEVICE_OUT_DISPLAY_PORT1] = "display-port1",
     [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = "speaker-and-display-port",
+    [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT1] = "speaker-and-display-port1",
     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
     [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
     [SND_DEVICE_OUT_BT_SCO_SWB] = "bt-sco-headset-swb",
@@ -802,7 +808,9 @@
     [SND_DEVICE_OUT_HDMI] = 18,
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
     [SND_DEVICE_OUT_DISPLAY_PORT] = 18,
+    [SND_DEVICE_OUT_DISPLAY_PORT1] = 18,
     [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = 14,
+    [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT1] = 14,
     [SND_DEVICE_OUT_BT_SCO] = 22,
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = 14,
     [SND_DEVICE_OUT_BT_SCO_WB] = 39,
@@ -1026,6 +1034,7 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_DISPLAY_PORT)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_DISPLAY_PORT1)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO)},
@@ -1728,6 +1737,23 @@
 
 static const char *platform_get_mixer_control(struct mixer_ctl *);
 
+static void platform_reset_edid_info(void *platform) {
+    ALOGV("%s:", __func__);
+    struct platform_data *my_data = (struct platform_data *)platform;
+    int i = 0, j = 0;
+    for (i = 0; i < MAX_CONTROLLERS; ++i) {
+        for (j = 0; j < MAX_STREAMS_PER_CONTROLLER; ++j) {
+            struct ext_disp_state *state = &my_data->ext_disp[i][j];
+            state->type = EXT_DISPLAY_TYPE_NONE;
+            if (state->edid_info) {
+                free(state->edid_info);
+                state->edid_info = NULL;
+            }
+            state->valid = false;
+        }
+    }
+}
+
 bool platform_send_gain_dep_cal(void *platform, int level) {
     bool ret_val = false;
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -1842,6 +1868,9 @@
         else if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_DISPLAY_PORT] > 0)
             strlcat(ec_ref_mixer_path, " display-port",
                     MIXER_PATH_MAX_LENGTH);
+        else if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_DISPLAY_PORT1] > 0)
+            strlcat(ec_ref_mixer_path, " display-port1",
+                    MIXER_PATH_MAX_LENGTH);
         else if (out_device & AUDIO_DEVICE_OUT_EARPIECE)
             strlcat(ec_ref_mixer_path, " handset",
                     MIXER_PATH_MAX_LENGTH);
@@ -2088,7 +2117,9 @@
     backend_tag_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
     backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
     backend_tag_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("display-port");
+    backend_tag_table[SND_DEVICE_OUT_DISPLAY_PORT1] = strdup("display-port1");
     backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("speaker-and-display-port");
+    backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT1] = strdup("speaker-and-display-port1");
     backend_tag_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
     backend_tag_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
     backend_tag_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
@@ -2175,7 +2206,9 @@
     hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI");
     hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT");
+    hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT1] = strdup("DISPLAY_PORT1");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT");
+    hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT1] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT1");
     hw_interface_table[SND_DEVICE_OUT_BT_SCO] = strdup("SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_BT_SCO_SWB] = strdup("SLIMBUS_7_RX");
@@ -3045,8 +3078,6 @@
     my_data->ambisonic_profile = false;
     my_data->slowtalk = false;
     my_data->hd_voice = false;
-    my_data->edid_info = NULL;
-    my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
     my_data->is_wsa_speaker = false;
     my_data->hw_dep_fd = -1;
     my_data->mono_speaker = SPKR_1;
@@ -3056,6 +3087,7 @@
     my_data->spkr_ch_map = NULL;
     my_data->use_sprk_default_sample_rate = true;
     my_data->fluence_in_voice_comm = false;
+    platform_reset_edid_info(my_data);
 
     //set max volume step for voice call
     property_get("ro.config.vc_call_vol_steps", value, TOSTRING(MAX_VOL_INDEX));
@@ -3633,6 +3665,12 @@
         strdup("Display Port RX SampleRate");
     my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels_mixer_ctl =
         strdup("Display Port RX Channels");
+    my_data->current_backend_cfg[DISP_PORT1_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("Display Port1 RX Bit Format");
+    my_data->current_backend_cfg[DISP_PORT1_RX_BACKEND].samplerate_mixer_ctl =
+        strdup("Display Port1 RX SampleRate");
+    my_data->current_backend_cfg[DISP_PORT1_RX_BACKEND].channels_mixer_ctl =
+        strdup("Display Port1 RX Channels");
 
     my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
         strdup("USB_AUDIO_RX Format");
@@ -3708,7 +3746,7 @@
     /* Initialize keep alive for HDMI/loopback silence */
     audio_extn_keep_alive_init(adev);
 
-    my_data->edid_info = NULL;
+    platform_reset_edid_info(my_data);
     free(snd_card_name);
     return my_data;
 }
@@ -3908,11 +3946,7 @@
     struct listnode *node;
 
     audio_extn_keep_alive_deinit();
-
-    if (my_data->edid_info) {
-        free(my_data->edid_info);
-        my_data->edid_info = NULL;
-    }
+    platform_reset_edid_info(my_data);
 
     if (be_dai_name_table) {
         free((void *)be_dai_name_table);
@@ -3996,11 +4030,7 @@
 
     /* deinit audio device arbitration */
     audio_extn_dev_arbi_deinit();
-
-    if (my_data->edid_info) {
-        free(my_data->edid_info);
-        my_data->edid_info = NULL;
-    }
+    platform_reset_edid_info(my_data);
 
     if (my_data->adev->mixer) {
         audio_extn_utils_close_snd_mixer(my_data->adev->mixer);
@@ -4128,7 +4158,8 @@
          */
         if (usecase->type == VOICE_CALL) {
             struct audio_device *adev = usecase->stream.out->dev;
-            if ((snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
+            if (((snd_device == SND_DEVICE_OUT_DISPLAY_PORT) ||
+                (snd_device == SND_DEVICE_OUT_DISPLAY_PORT1)) &&
                 adev->dp_allowed_for_voice &&
                 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_USB_HEADSET_MIC)) {
                 strlcat(mixer_path, "-and-usb-headset-mic", MIXER_PATH_MAX_LENGTH);
@@ -4901,6 +4932,8 @@
                         port = HDMI_RX_BACKEND;
                 else if (strcmp(backend_tag_table[snd_device], "display-port") == 0)
                         port = DISP_PORT_RX_BACKEND;
+                else if (strcmp(backend_tag_table[snd_device], "display-port1") == 0)
+                        port = DISP_PORT1_RX_BACKEND;
                 else if ((strcmp(backend_tag_table[snd_device], "usb-headphones") == 0) ||
                            (strcmp(backend_tag_table[snd_device], "usb-headset") == 0))
                         port = USB_AUDIO_RX_BACKEND;
@@ -5508,6 +5541,17 @@
             new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_DISPLAY_PORT;
         ret = 0;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT1 &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_DISPLAY_PORT1)) {
+        *num_devices = 2;
+        if (my_data->is_vbat_speaker)
+            new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_VBAT;
+        else if (my_data->is_wsa_speaker)
+            new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_WSA;
+        else
+            new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+        new_snd_devices[1] = SND_DEVICE_OUT_DISPLAY_PORT1;
+        ret = 0;
     } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
                !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
         *num_devices = 2;
@@ -5618,21 +5662,118 @@
     return ret;
 }
 
-int platform_get_ext_disp_type(void *platform)
-{
-    int disp_type;
-    struct platform_data *my_data = (struct platform_data *)platform;
+/*
+ * returns index for mixer controls
+ *
+ * example: max controllers = 2, max streams = 4
+ * controller = 0, stream = 0 => Index 0
+ * ...
+ * controller = 0, stream = 3 => Index 3
+ * controller = 1, stream = 0 => Index 4
+ * ...
+ * controller = 1, stream = 3 => Index 7
+ */
+int platform_get_display_port_ctl_index(int controller, int stream) {
 
-    if (my_data->ext_disp_type != EXT_DISPLAY_TYPE_NONE) {
+    if (controller < 0 || controller >= MAX_CONTROLLERS ||
+            stream < 0 || stream >= MAX_STREAMS_PER_CONTROLLER) {
+        ALOGE("%s: Invalid controller/stream - %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    return ((controller % MAX_CONTROLLERS) * MAX_STREAMS_PER_CONTROLLER) +
+            (stream % MAX_STREAMS_PER_CONTROLLER);
+}
+
+int platform_set_ext_display_device_v2(void *platform, int controller, int stream)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    struct mixer_ctl *ctl = NULL;
+    int ctl_index = 0;
+    const char *ctl_name_prefix = "External Display";
+    const char *ctl_name_suffix = "Audio Device";
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    int device_values[2] = {-1, -1};
+
+    if (!audio_extn_is_display_port_enabled()) {
+        ALOGE("%s: display port is not supported", __func__);
+        return -EINVAL;
+    }
+
+    ctl_index = platform_get_display_port_ctl_index(controller, stream);
+    if (-EINVAL == ctl_index) {
+        ALOGE("%s: Unknown controller/stream %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    if (0 == ctl_index)
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                 "%s %s", ctl_name_prefix, ctl_name_suffix);
+    else
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                 "%s%d %s", ctl_name_prefix, ctl_index, ctl_name_suffix);
+
+    device_values[0] = controller;
+    device_values[1] = stream;
+
+    ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+              __func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+
+    ALOGV("%s: controller/stream: %d/%d", __func__, device_values[0],
+          device_values[1]);
+
+    return mixer_ctl_set_array(ctl, device_values, ARRAY_SIZE(device_values));
+}
+
+int platform_get_ext_disp_type(void *platform) {
+    return platform_get_ext_disp_type_v2(platform, 0, 0);
+}
+
+int platform_get_ext_disp_type_v2(void *platform, int controller, int stream)
+{
+    int disp_type = EXT_DISPLAY_TYPE_NONE;
+    int ctl_index = 0;
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct ext_disp_state *disp = NULL;
+
+    ctl_index = platform_get_display_port_ctl_index(controller, stream);
+    if (-EINVAL == ctl_index) {
+        ALOGE("%s: Unknown controller/stream %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    disp = &my_data->ext_disp[controller][stream];
+    if (disp->type != EXT_DISPLAY_TYPE_NONE) {
          ALOGD("%s: Returning cached ext disp type:%s",
-               __func__, (my_data->ext_disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
-         return my_data->ext_disp_type;
+               __func__, (disp->type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+         return disp->type;
     }
 
     if (audio_extn_is_display_port_enabled()) {
         struct audio_device *adev = my_data->adev;
-        struct mixer_ctl *ctl;
-        char *mixer_ctl_name = "External Display Type";
+        struct mixer_ctl *ctl = NULL;
+        const char *ctl_name_prefix = "External Display";
+        const char *ctl_name_suffix = "Type";
+        char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+
+        if (0 == ctl_index)
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                     "%s %s", ctl_name_prefix, ctl_name_suffix);
+        else
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                     "%s%d %s", ctl_name_prefix, ctl_index, ctl_name_suffix);
+
+        ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
 
         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
         if (!ctl) {
@@ -5649,8 +5790,12 @@
     } else {
         disp_type = EXT_DISPLAY_TYPE_HDMI;
     }
-    my_data->ext_disp_type = disp_type;
-    ALOGD("%s: ext disp type:%s", __func__, (disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+
+    disp->type = disp_type;
+
+    ALOGD("%s: ext disp type: %s", __func__,
+          (disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+
     return disp_type;
 }
 
@@ -5668,6 +5813,8 @@
     audio_channel_mask_t channel_mask = (in == NULL) ?
                                 AUDIO_CHANNEL_IN_MONO : in->channel_mask;
     int channel_count = popcount(channel_mask);
+    int controller = -1;
+    int stream = -1;
 
     ALOGV("%s: enter: output devices(%#x)", __func__, devices);
     if (devices == AUDIO_DEVICE_NONE ||
@@ -5676,6 +5823,18 @@
         goto exit;
     }
 
+    if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+        controller = out->extconn.cs.controller;
+        stream = out->extconn.cs.stream;
+
+        if (controller < 0 || controller >= MAX_CONTROLLERS ||
+                stream < 0 || stream >= MAX_STREAMS_PER_CONTROLLER) {
+            ALOGE("%s: Invalid controller/stream - %d/%d",
+                  __func__, controller, stream);
+            goto exit;
+        }
+    }
+
     if (popcount(devices) == 2) {
         bool is_active_voice_call = false;
 
@@ -5739,15 +5898,17 @@
             snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_LINE;
         } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
-            switch(my_data->ext_disp_type) {
+            switch(my_data->ext_disp[controller][stream].type) {
                 case EXT_DISPLAY_TYPE_HDMI:
                     snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
                     break;
                 case EXT_DISPLAY_TYPE_DP:
-                    snd_device = SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT;
+                    snd_device = SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT +
+                        ((controller * MAX_STREAMS_PER_CONTROLLER) + stream);
                     break;
                 default:
-                    ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+                    ALOGE("%s: Invalid disp_type %d", __func__,
+                          my_data->ext_disp[controller][stream].type);
                     goto exit;
             }
         } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
@@ -5931,13 +6092,14 @@
             snd_device = SND_DEVICE_OUT_USB_HEADSET;
         } else if ((devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
                    adev->dp_allowed_for_voice) {
-            switch(my_data->ext_disp_type) {
+            switch(my_data->ext_disp[controller][stream].type) {
                 case EXT_DISPLAY_TYPE_DP:
-                    snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+                    snd_device = SND_DEVICE_OUT_DISPLAY_PORT +
+                        ((controller * MAX_STREAMS_PER_CONTROLLER) + stream);
                     break;
                 default:
                     ALOGE("%s: Invalid disp_type %d", __func__,
-                           my_data->ext_disp_type);
+                           my_data->ext_disp[controller][stream].type);
                     goto exit;
             }
         } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
@@ -6027,15 +6189,17 @@
     } else if (devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
         snd_device = SND_DEVICE_OUT_BT_A2DP;
     } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
-            switch(my_data->ext_disp_type) {
+            switch(my_data->ext_disp[controller][stream].type) {
                 case EXT_DISPLAY_TYPE_HDMI:
                     snd_device = SND_DEVICE_OUT_HDMI;
                     break;
                 case EXT_DISPLAY_TYPE_DP:
-                    snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+                    snd_device = SND_DEVICE_OUT_DISPLAY_PORT +
+                        ((controller * MAX_STREAMS_PER_CONTROLLER) + stream);
                     break;
                 default:
-                    ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+                    ALOGE("%s: Invalid disp_type %d", __func__,
+                          my_data->ext_disp[controller][stream].type);
                     goto exit;
             }
     } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
@@ -6881,13 +7045,22 @@
     return snd_device;
 }
 
-int platform_set_hdmi_channels(void *platform,  int channel_count)
+int platform_set_hdmi_channels(void *platform,  int channel_count) {
+    return platform_set_hdmi_channels_v2(platform, channel_count, 0, 0);
+}
+
+int platform_set_hdmi_channels_v2(void *platform,  int channel_count,
+                               int controller, int stream)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    struct mixer_ctl *ctl;
     const char *channel_cnt_str = NULL;
-    char *mixer_ctl_name;
+    int ctl_index = 0;
+    struct mixer_ctl *ctl = NULL;
+    const char *ctl_name_prefix = "Display Port";
+    const char *ctl_name_suffix = "RX Channels";
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+
     switch (channel_count) {
     case 8:
         channel_cnt_str = "Eight"; break;
@@ -6905,38 +7078,64 @@
         channel_cnt_str = "Two"; break;
     }
 
-    switch(my_data->ext_disp_type) {
+    ctl_index = platform_get_display_port_ctl_index(controller, stream);
+    if (-EINVAL == ctl_index) {
+        ALOGE("%s: Unknown controller/stream %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    switch(my_data->ext_disp[controller][stream].type) {
         case EXT_DISPLAY_TYPE_HDMI:
-            mixer_ctl_name = "HDMI_RX Channels";
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "HDMI_RX Channels");
             break;
         case EXT_DISPLAY_TYPE_DP:
-            mixer_ctl_name = "Display Port RX Channels";
-            break;
+            if (!audio_extn_is_display_port_enabled()) {
+                ALOGE("%s: display port is not supported", __func__);
+                return -EINVAL;
+            }
+
+            if (0 == ctl_index)
+                snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                         "%s %s", ctl_name_prefix, ctl_name_suffix);
+            else
+                snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                         "%s%d %s", ctl_name_prefix, ctl_index, ctl_name_suffix);
         default:
-            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            ALOGE("%s: Invalid disp_type %d", __func__,
+                  my_data->ext_disp[controller][stream].type);
             return -EINVAL;
     }
 
+    ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
+
     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
               __func__, mixer_ctl_name);
         return -EINVAL;
     }
-    ALOGV("Ext disp channel count: %s", channel_cnt_str);
+
+    ALOGV("%s: ext disp channel count: %s", __func__, channel_cnt_str);
     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
     return 0;
 }
 
-int platform_edid_get_max_channels(void *platform)
+int platform_edid_get_max_channels(void *platform) {
+    return platform_edid_get_max_channels_v2(platform, 0, 0);
+}
+
+int platform_edid_get_max_channels_v2(void *platform, int controller, int stream)
 {
     int channel_count;
     int max_channels = 2;
     int i = 0, ret = 0;
     struct platform_data *my_data = (struct platform_data *)platform;
     edid_audio_info *info = NULL;
-    ret = platform_get_edid_info(platform);
-    info = (edid_audio_info *)my_data->edid_info;
+
+    ret = platform_get_edid_info_v2(platform, controller, stream);
+    if(ret == 0)
+        info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
 
     if(ret == 0 && info != NULL) {
         for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
@@ -7813,20 +8012,31 @@
                             value, sizeof(value));
 
     if (ret >= 0) {
-        if (my_data->ext_disp_type == EXT_DISPLAY_TYPE_DP &&
-            adev->dp_allowed_for_voice)
-            strlcpy(value, "true", sizeof(value));
-        else
-            strlcpy(value, "false", sizeof(value));
-
+        bool enabled = false;
+        int i = 0, j = 0;
+        if (adev->dp_allowed_for_voice) {
+            for (i = 0; i < MAX_CONTROLLERS; ++i) {
+                for (j = 0; j < MAX_STREAMS_PER_CONTROLLER; ++j) {
+                    if (my_data->ext_disp[i][j].type == EXT_DISPLAY_TYPE_DP) {
+                        enabled = true;
+                        break;
+                    }
+                }
+            }
+        }
+        strlcpy(value, enabled ? "true" : "false", sizeof(value));
         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_DP_FOR_VOICE_USECASE, value);
     }
 
     ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_DP_CHANNEL_MASK,
                             value, sizeof(value));
     if (ret >= 0) {
-        ret = platform_get_edid_info(platform);
-        edid_audio_info *info = (edid_audio_info *)my_data->edid_info;
+        int controller = 0, stream = 0;
+        edid_audio_info *info = NULL;
+        platform_get_controller_stream_from_params(query, &controller, &stream);
+        ret = platform_get_edid_info_v2(platform, controller, stream);
+        if (ret == 0)
+            info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
         if (ret == 0 && info != NULL) {
             str_parms_add_int(reply, AUDIO_PARAMETER_KEY_DP_CHANNEL_MASK, info->channel_mask);
         }
@@ -8139,6 +8349,7 @@
  * configures afe with bit width and Sample Rate
  */
 static int platform_set_codec_backend_cfg(struct audio_device* adev,
+                                          struct audio_usecase *usecase,
                          snd_device_t snd_device, struct audio_backend_cfg backend_cfg)
 {
     int ret = -EINVAL;
@@ -8150,6 +8361,13 @@
     audio_format_t format = backend_cfg.format;
     bool passthrough_enabled = backend_cfg.passthrough_enabled;
     struct audio_device_config_param *adev_device_cfg_ptr = adev->device_cfg_params;
+    int controller = -1;
+    int stream = -1;
+
+    if (usecase) {
+        controller = usecase->stream.out->extconn.cs.controller;
+        stream = usecase->stream.out->extconn.cs.stream;
+    }
 
     /* Override the config params if client has already set them */
     adev_device_cfg_ptr += backend_idx;
@@ -8330,8 +8548,11 @@
         my_data->current_backend_cfg[backend_idx].channels = channels;
 
         if ((backend_idx == HDMI_RX_BACKEND) ||
-                (backend_idx == DISP_PORT_RX_BACKEND))
-            platform_set_edid_channels_configuration(adev->platform, channels, backend_idx, snd_device);
+                (backend_idx == DISP_PORT_RX_BACKEND) ||
+                (backend_idx == DISP_PORT1_RX_BACKEND))
+            platform_set_edid_channels_configuration_v2(adev->platform, channels,
+                                                     backend_idx, snd_device,
+                                                     controller, stream);
 
         ALOGD("%s:becf: afe: %s set to %s ", __func__,
                my_data->current_backend_cfg[backend_idx].channels_mixer_ctl,
@@ -8341,6 +8562,7 @@
 
     bool set_ext_disp_format = false, set_mi2s_tx_data_format = false;
     char *ext_disp_format = NULL;
+    bool set_ext_disp_device_idx = false;
 
     if (backend_idx == HDMI_RX_BACKEND) {
         ext_disp_format = "HDMI RX Format";
@@ -8348,6 +8570,11 @@
     } else if (backend_idx == DISP_PORT_RX_BACKEND) {
         ext_disp_format = "Display Port RX Format";
         set_ext_disp_format = true;
+        set_ext_disp_device_idx = true;
+    } else if (backend_idx == DISP_PORT1_RX_BACKEND) {
+        ext_disp_format = "Display Port1 RX Format";
+        set_ext_disp_format = true;
+        set_ext_disp_device_idx = true;
     } else if (backend_idx == SPDIF_TX_BACKEND) {
         ext_disp_format = "PRI SPDIF TX Format";
         set_mi2s_tx_data_format = true;
@@ -8383,6 +8610,41 @@
         }
         my_data->current_backend_cfg[backend_idx].format = format;
     }
+    if (set_ext_disp_device_idx && usecase) {
+        struct mixer_ctl *ctl;
+        int ctl_index = 0;
+        const char *ctl_name_prefix = "Display Port";
+        const char *ctl_name_suffix = "RX DEVICE IDX";
+        char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+        int dev[] = {controller, stream};
+
+        ctl_index = platform_get_display_port_ctl_index(controller, stream);
+        if (-EINVAL == ctl_index) {
+            ALOGE("%s: Unknown controller/stream %d/%d",
+                  __func__, controller, stream);
+            return -EINVAL;
+        }
+
+        if (0 == ctl_index)
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                     "%s %s", ctl_name_prefix, ctl_name_suffix);
+        else
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                     "%s%d %s", ctl_name_prefix, ctl_index, ctl_name_suffix);
+
+        ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
+
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
+                  __func__, ext_disp_format);
+            return -EINVAL;
+        }
+
+        mixer_ctl_set_array(ctl, dev, ARRAY_SIZE(dev));
+        my_data->current_backend_cfg[backend_idx].controller = controller;
+        my_data->current_backend_cfg[backend_idx].stream = stream;
+    }
     if (set_ext_disp_format) {
         struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, ext_disp_format);
         if (!ctl) {
@@ -8442,9 +8704,26 @@
     unsigned int sample_rate;
     int channels, max_supported_channels = 0;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
-    edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
+    edid_audio_info *edid_info = NULL;
     bool passthrough_enabled = false;
+    int controller = -1;
+    int stream = -1;
 
+    if (!usecase) {
+        ALOGE("%s: becf: HDMI: usecase is NULL", __func__);
+        return;
+    }
+
+    controller = usecase->stream.out->extconn.cs.controller;
+    stream = usecase->stream.out->extconn.cs.stream;
+
+    if (controller < 0 || controller >= MAX_CONTROLLERS ||
+            stream < 0 || stream >= MAX_STREAMS_PER_CONTROLLER) {
+        controller = 0;
+        stream = 0;
+    }
+
+    edid_info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
     bit_width = hdmi_backend_cfg->bit_width;
     sample_rate = hdmi_backend_cfg->sample_rate;
     channels = hdmi_backend_cfg->channels;
@@ -8464,7 +8743,8 @@
     // default backend
     if (!passthrough_enabled) {
 
-        max_supported_channels = platform_edid_get_max_channels(my_data);
+        max_supported_channels = platform_edid_get_max_channels_v2(my_data,
+                                                                controller, stream);
 
         //Check EDID info for supported samplerate
         if (!audio_extn_edid_is_supported_sr(edid_info,sample_rate)) {
@@ -8537,7 +8817,11 @@
     struct platform_data *my_data = (struct platform_data *)adev->platform;
     int na_mode = platform_get_native_support();
     bool channels_updated = false;
+    bool display_port_updated = false;
     struct audio_device_config_param *adev_device_cfg_ptr = adev->device_cfg_params;
+    int controller = -1;
+    int stream = -1;
+
 
     /*BT devices backend is not configured from HAL hence skip*/
     if (snd_device == SND_DEVICE_OUT_BT_A2DP ||
@@ -8550,6 +8834,9 @@
         return backend_change;
     }
 
+    controller = usecase->stream.out->extconn.cs.controller;
+    stream = usecase->stream.out->extconn.cs.stream;
+
     backend_idx = platform_get_backend_index(snd_device);
 
     bit_width = backend_cfg->bit_width;
@@ -8764,7 +9051,8 @@
             channels_updated = true;
     }
 
-    if (backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) {
+    if (backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND ||
+             backend_idx == DISP_PORT1_RX_BACKEND) {
         struct audio_backend_cfg hdmi_backend_cfg;
         hdmi_backend_cfg.bit_width = bit_width;
         hdmi_backend_cfg.sample_rate = sample_rate;
@@ -8790,7 +9078,15 @@
         if (channels != my_data->current_backend_cfg[backend_idx].channels)
             channels_updated = true;
 
-        platform_set_edid_channels_configuration(adev->platform, channels, backend_idx, snd_device);
+        platform_set_edid_channels_configuration_v2(adev->platform, channels,
+                                                 backend_idx, snd_device,
+                                                 controller, stream);
+
+        if ((controller != my_data->current_backend_cfg[backend_idx].controller) ||
+             (stream != my_data->current_backend_cfg[backend_idx].stream)) {
+            ALOGD("%s:becf: afe: display port changed", __func__);
+            display_port_updated = true;
+        }
     }
 
     ALOGI("%s:becf: afe: Codec selected backend: %d updated bit width: %d and sample rate: %d",
@@ -8800,7 +9096,8 @@
     // is not same as current backend comfiguration
     if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
         (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate) ||
-         passthrough_enabled || channels_updated || service_interval_update ) {
+         passthrough_enabled || channels_updated || service_interval_update ||
+         display_port_updated) {
         backend_cfg->bit_width = bit_width;
         backend_cfg->sample_rate = sample_rate;
         backend_cfg->channels = channels;
@@ -8859,6 +9156,8 @@
         backend_cfg.sample_rate = usecase->stream.out->sample_rate;
         backend_cfg.format = usecase->stream.out->format;
         backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
+        backend_cfg.controller = 0;
+        backend_cfg.stream = 0;
     }
     if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
                 (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
@@ -8896,7 +9195,7 @@
         ALOGI("%s: new_snd_devices[%d] is %d", __func__, i, new_snd_devices[i]);
         if ((platform_check_codec_backend_cfg(adev, usecase, new_snd_devices[i],
                                              &backend_cfg))) {
-            ret = platform_set_codec_backend_cfg(adev, new_snd_devices[i],
+            ret = platform_set_codec_backend_cfg(adev, usecase, new_snd_devices[i],
                                            backend_cfg);
             if (!ret) {
                 ret = true;
@@ -9056,7 +9355,7 @@
           platform_get_snd_device_name(snd_device));
     if (platform_check_capture_codec_backend_cfg(adev, backend_idx,
                                                  &backend_cfg, snd_device)) {
-        ret = platform_set_codec_backend_cfg(adev, snd_device,
+        ret = platform_set_codec_backend_cfg(adev, usecase, snd_device,
                                              backend_cfg);
         if(!ret)
             return true;
@@ -9499,42 +9798,68 @@
 
 int platform_get_edid_info(void *platform)
 {
+    return platform_get_edid_info_v2(platform, 0, 0);
+}
+
+int platform_get_edid_info_v2(void *platform, int controller, int stream)
+{
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
     char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
     int ret, count;
-    char *mix_ctl_name;
-    struct mixer_ctl *ctl;
     char edid_data[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE + 1] = {0};
-    edid_audio_info *info;
+    struct ext_disp_state *state = NULL;
+    int ctl_index = 0;
+    struct mixer_ctl *ctl = NULL;
+    const char *ctl_name_prefix = "Display Port";
+    const char *ctl_name_suffix = "EDID";
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
 
-    if (my_data->edid_valid) {
+    ctl_index = platform_get_display_port_ctl_index(controller, stream);
+    if (-EINVAL == ctl_index) {
+        ALOGE("%s: Unknown controller/stream %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    state = &my_data->ext_disp[controller][stream];
+    if (state->valid) {
         /* use cached edid */
         return 0;
     }
 
-    switch(my_data->ext_disp_type) {
+    switch(state->type) {
         case EXT_DISPLAY_TYPE_HDMI:
-            mix_ctl_name = "HDMI EDID";
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "HDMI EDID");
             break;
         case EXT_DISPLAY_TYPE_DP:
-            mix_ctl_name = "Display Port EDID";
+            if (!audio_extn_is_display_port_enabled()) {
+                ALOGE("%s: display port is not supported", __func__);
+                return -EINVAL;
+            }
+
+            if (0 == ctl_index)
+                snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                         "%s %s", ctl_name_prefix, ctl_name_suffix);
+            else
+                snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                         "%s%d %s", ctl_name_prefix, ctl_index, ctl_name_suffix);
             break;
         default:
-            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            ALOGE("%s: Invalid disp_type %d", __func__, state->type);
             return -EINVAL;
     }
 
-    if (my_data->edid_info == NULL) {
-        my_data->edid_info =
+    if (state->edid_info == NULL)
+        state->edid_info =
             (struct edid_audio_info *)calloc(1, sizeof(struct edid_audio_info));
-    }
 
-    info = my_data->edid_info;
-    ctl = mixer_get_ctl_by_name(adev->mixer, mix_ctl_name);
+    ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
-              __func__, mix_ctl_name);
+              __func__, mixer_ctl_name);
         goto fail;
     }
 
@@ -9554,50 +9879,80 @@
     edid_data[0] = count;
     memcpy(&edid_data[1], block, count);
 
-    if (!audio_extn_edid_get_sink_caps(info, edid_data)) {
+    ALOGV("%s: received edid data: count %d", __func__, edid_data[0]);
+
+    if (!audio_extn_edid_get_sink_caps(state->edid_info, edid_data)) {
         ALOGE("%s: Failed to get extn disp sink capabilities", __func__);
         goto fail;
     }
-    my_data->edid_valid = true;
+    state->valid = true;
     return 0;
 fail:
-    if (my_data->edid_info) {
-        free(my_data->edid_info);
-        my_data->edid_info = NULL;
-        my_data->edid_valid = false;
+    if (state->edid_info) {
+        free(state->edid_info);
+        state->edid_info = NULL;
+        state->valid = false;
     }
     ALOGE("%s: return -EINVAL", __func__);
     return -EINVAL;
 }
 
-
 int platform_set_channel_allocation(void *platform, int channel_alloc)
 {
-    struct mixer_ctl *ctl;
-    char *mixer_ctl_name;
+    return platform_set_channel_allocation_v2(platform, channel_alloc, 0, 0);
+}
+
+int platform_set_channel_allocation_v2(void *platform, int channel_alloc,
+                                    int controller, int stream)
+{
     int ret;
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
+    int ctl_index = 0;
+    struct mixer_ctl *ctl = NULL;
+    const char *ctl_name_prefix = "Display Port";
+    const char *ctl_name_suffix = "RX CA";
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
 
-    switch(my_data->ext_disp_type) {
+    ctl_index = platform_get_display_port_ctl_index(controller, stream);
+    if (-EINVAL == ctl_index) {
+        ALOGE("%s: Unknown controller/stream %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    switch(my_data->ext_disp[controller][stream].type) {
         case EXT_DISPLAY_TYPE_HDMI:
-            mixer_ctl_name = "HDMI RX CA";
-        break;
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "HDMI RX CA");
+            break;
         case EXT_DISPLAY_TYPE_DP:
-            mixer_ctl_name = "Display Port RX CA";
+            if (!audio_extn_is_display_port_enabled()) {
+                ALOGE("%s: display port is not supported", __func__);
+                return -EINVAL;
+            }
+
+            if (0 == ctl_index)
+                snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                         "%s %s", ctl_name_prefix, ctl_name_suffix);
+            else
+                snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                         "%s%d %s", ctl_name_prefix, ctl_index, ctl_name_suffix);
             break;
         default:
-            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            ALOGE("%s: Invalid disp_type %d", __func__,
+                  my_data->ext_disp[controller][stream].type);
             return -EINVAL;
     }
 
+    ALOGV("%s: mixer ctl name: %s", __func__, mixer_ctl_name);
     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
               __func__, mixer_ctl_name);
         return -EINVAL;
     }
-    ALOGD(":%s channel allocation = 0x%x", __func__, channel_alloc);
+
+    ALOGV("%s: channel allocation: 0x%x", __func__, channel_alloc);
     ret = mixer_ctl_set_value(ctl, 0, channel_alloc);
 
     if (ret < 0) {
@@ -9783,6 +10138,7 @@
          *sample_rate = stream_sr;
 
     if ((snd_device == SND_DEVICE_OUT_HDMI) || (snd_device == SND_DEVICE_OUT_DISPLAY_PORT) ||
+                  (snd_device == SND_DEVICE_OUT_DISPLAY_PORT1) ||
                   (snd_device == SND_DEVICE_OUT_USB_HEADSET))
         *sample_rate = platform_get_supported_copp_sampling_rate(stream_sr);
 
@@ -9825,18 +10181,12 @@
     list_add_tail(&app_type_entry_list, &ap->node);
 }
 
-void platform_reset_edid_info(void *platform) {
-
-    ALOGV("%s:", __func__);
-    struct platform_data *my_data = (struct platform_data *)platform;
-    if (my_data->edid_info) {
-        ALOGV("%s :free edid", __func__);
-        free(my_data->edid_info);
-        my_data->edid_info = NULL;
-    }
+bool platform_is_edid_supported_format(void *platform, int format) {
+    return platform_is_edid_supported_format_v2(platform, format, 0, 0);
 }
 
-bool platform_is_edid_supported_format(void *platform, int format)
+bool platform_is_edid_supported_format_v2(void *platform,
+                                          int format, int controller, int stream)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     edid_audio_info *info = NULL;
@@ -9851,8 +10201,9 @@
         return false;
     }
 
-    ret = platform_get_edid_info(platform);
-    info = (edid_audio_info *)my_data->edid_info;
+    ret = platform_get_edid_info_v2(platform, controller, stream);
+    if (ret == 0)
+        info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
     if (ret == 0 && info != NULL) {
         for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
              /*
@@ -9874,12 +10225,20 @@
 
 bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate)
 {
+    return platform_is_edid_supported_sample_rate_v2(platform, sample_rate, 0, 0);
+}
+
+bool platform_is_edid_supported_sample_rate_v2(void *platform,
+                                               int sample_rate,
+                                               int controller, int stream)
+{
     struct platform_data *my_data = (struct platform_data *)platform;
     edid_audio_info *info = NULL;
     int ret = 0;
 
-    ret = platform_get_edid_info(platform);
-    info = (edid_audio_info *)my_data->edid_info;
+    ret = platform_get_edid_info_v2(platform, controller, stream);
+    if (ret == 0)
+        info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
     if (ret == 0 && info != NULL) {
         return audio_extn_edid_is_supported_sr(info, sample_rate);
     }
@@ -9887,14 +10246,15 @@
     return false;
 }
 
-int platform_edid_get_highest_supported_sr(void *platform)
+int platform_edid_get_highest_supported_sr_v2(void *platform, int controller, int stream)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     edid_audio_info *info = NULL;
     int ret = 0;
 
-    ret = platform_get_edid_info(platform);
-    info = (edid_audio_info *)my_data->edid_info;
+    ret = platform_get_edid_info_v2(platform, controller, stream);
+    if (ret == 0)
+        info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
     if (ret == 0 && info != NULL) {
         return audio_extn_edid_get_highest_supported_sr(info);
     }
@@ -9902,12 +10262,25 @@
     return 0;
 }
 
+int platform_edid_get_highest_supported_sr(void *platform)
+{
+    return  platform_edid_get_highest_supported_sr_v2(platform, 0, 0);
+}
+
 bool platform_spkr_use_default_sample_rate(void *platform) {
     struct platform_data *my_data = (struct platform_data *)platform;
     return my_data->use_sprk_default_sample_rate;
 }
 
-int platform_set_edid_channels_configuration(void *platform, int channels, int backend_idx, snd_device_t snd_device) {
+int platform_set_edid_channels_configuration(void *platform, int channels,
+                                     int backend_idx, snd_device_t snd_device) {
+    return platform_set_edid_channels_configuration_v2(platform, channels,
+                        backend_idx, snd_device, 0, 0);
+}
+
+int platform_set_edid_channels_configuration_v2(void *platform, int channels,
+                                     int backend_idx, snd_device_t snd_device,
+                                     int controller, int stream) {
 
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
@@ -9919,17 +10292,28 @@
     int be_idx = -1;
 
     if ((backend_idx != HDMI_RX_BACKEND) &&
-            (backend_idx != DISP_PORT_RX_BACKEND)) {
+            (backend_idx != DISP_PORT_RX_BACKEND) &&
+            (backend_idx != DISP_PORT1_RX_BACKEND)) {
         ALOGE("%s: Invalid backend idx %d", __func__, backend_idx);
         return -EINVAL;
     }
 
+    if (controller < 0 || controller >= MAX_CONTROLLERS ||
+            stream < 0 || stream >= MAX_STREAMS_PER_CONTROLLER) {
+        ALOGE("%s: Invalid controller/stream - %d/%d",
+              __func__, controller, stream);
+        return -EINVAL;
+    }
+
+    // backend port id
     be_idx = platform_get_snd_device_backend_index(snd_device);
-    ret = platform_get_edid_info(platform);
-    info = (edid_audio_info *)my_data->edid_info;
+
+    ret = platform_get_edid_info_v2(platform, controller, stream);
+    info = (edid_audio_info *)my_data->ext_disp[controller][stream].edid_info;
     adev_device_cfg_ptr += backend_idx;
     if(ret == 0 && info != NULL) {
         if (channels > 2) {
+
             ALOGV("%s:able to get HDMI/DP sink capabilities multi channel playback",
                    __func__);
             for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
@@ -9947,7 +10331,7 @@
              */
             if (adev_device_cfg_ptr->use_client_dev_cfg) {
                 platform_set_channel_map(platform, adev_device_cfg_ptr->dev_cfg_params.channels,
-                                   (char *)adev_device_cfg_ptr->dev_cfg_params.channel_map, -1, be_idx);
+                                     (char *)adev_device_cfg_ptr->dev_cfg_params.channel_map, -1, be_idx);
             } else {
                 platform_set_channel_map(platform, channel_count, info->channel_map, -1, be_idx);
             }
@@ -9955,10 +10339,12 @@
             if (adev_device_cfg_ptr->use_client_dev_cfg) {
                 ALOGV("%s:: Setting client selected CA %d", __func__,
                             adev_device_cfg_ptr->dev_cfg_params.channel_allocation);
-                platform_set_channel_allocation(platform,
-                       adev_device_cfg_ptr->dev_cfg_params.channel_allocation);
+                platform_set_channel_allocation_v2(platform,
+                       adev_device_cfg_ptr->dev_cfg_params.channel_allocation,
+                       controller, stream);
             } else {
-                platform_set_channel_allocation(platform, info->channel_allocation);
+                platform_set_channel_allocation_v2(platform, info->channel_allocation,
+                                                controller, stream);
            }
         } else {
             if (adev_device_cfg_ptr->use_client_dev_cfg) {
@@ -9969,16 +10355,21 @@
                 default_channelMap[1] = PCM_CHANNEL_FR;
             }
             platform_set_channel_map(platform, 2, default_channelMap, -1, be_idx);
-            platform_set_channel_allocation(platform,0);
+            platform_set_channel_allocation_v2(platform, 0, controller, stream);
         }
     }
 
     return 0;
 }
 
+void platform_cache_edid_v2(void * platform, int controller, int stream)
+{
+    platform_get_edid_info_v2(platform, controller, stream);
+}
+
 void platform_cache_edid(void * platform)
 {
-    platform_get_edid_info(platform);
+    platform_get_edid_info_v2(platform, 0, 0);
 }
 
 void platform_invalidate_backend_config(void * platform,snd_device_t snd_device)
@@ -9995,14 +10386,16 @@
     backend_cfg.passthrough_enabled = false;
 
     backend_idx = platform_get_backend_index(snd_device);
-    platform_set_codec_backend_cfg(adev, snd_device, backend_cfg);
+    platform_set_codec_backend_cfg(adev, NULL, snd_device, backend_cfg);
     my_data->current_backend_cfg[backend_idx].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     my_data->current_backend_cfg[backend_idx].channels = CODEC_BACKEND_DEFAULT_CHANNELS;
     my_data->current_backend_cfg[backend_idx].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     my_data->current_backend_cfg[backend_idx].format = AUDIO_FORMAT_PCM_16_BIT;
+    my_data->current_backend_cfg[backend_idx].controller = 0;
+    my_data->current_backend_cfg[backend_idx].stream = 0;
 }
 
-void platform_invalidate_hdmi_config(void * platform)
+void platform_invalidate_hdmi_config_v2(void * platform, int controller, int stream)
 {
     //reset ext display EDID info
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -10011,31 +10404,45 @@
     int backend_idx;
     snd_device_t snd_device;
 
+    if (controller < 0 || controller >= MAX_CONTROLLERS ||
+            stream < 0 || stream >= MAX_STREAMS_PER_CONTROLLER) {
+        ALOGE("%s: Invalid controller/stream - %d/%d",
+              __func__, controller, stream);
+        return;
+    }
+
     backend_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     backend_cfg.channels = DEFAULT_HDMI_OUT_CHANNELS;
     backend_cfg.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     backend_cfg.format = 0;
     backend_cfg.passthrough_enabled = false;
 
-    my_data->edid_valid = false;
-    if (my_data->edid_info) {
-        memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
+    struct ext_disp_state *state = &my_data->ext_disp[controller][stream];
+    state->valid = false;
+    if (state->edid_info) {
+        memset(state->edid_info, 0, sizeof(struct edid_audio_info));
     }
 
-    if (my_data->ext_disp_type == EXT_DISPLAY_TYPE_HDMI) {
+    if (my_data->ext_disp[controller][stream].type == EXT_DISPLAY_TYPE_HDMI) {
         //reset HDMI_RX_BACKEND to default values
         backend_idx = HDMI_RX_BACKEND;
         snd_device = SND_DEVICE_OUT_HDMI;
     } else {
         //reset Display port BACKEND to default values
-        backend_idx = DISP_PORT_RX_BACKEND;
-        snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+        backend_idx = DISP_PORT_RX_BACKEND +
+                      ((controller * MAX_STREAMS_PER_CONTROLLER) + stream);
+        snd_device = SND_DEVICE_OUT_DISPLAY_PORT +
+                     ((controller * MAX_STREAMS_PER_CONTROLLER) + stream);
     }
-    platform_set_codec_backend_cfg(adev, snd_device, backend_cfg);
+    platform_set_codec_backend_cfg(adev, NULL, snd_device, backend_cfg);
     my_data->current_backend_cfg[backend_idx].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     my_data->current_backend_cfg[backend_idx].channels = DEFAULT_HDMI_OUT_CHANNELS;
     my_data->current_backend_cfg[backend_idx].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
-    my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
+    my_data->ext_disp[controller][stream].type = EXT_DISPLAY_TYPE_NONE;
+}
+
+void platform_invalidate_hdmi_config(void * platform) {
+    platform_invalidate_hdmi_config_v2(platform, 0, 0);
 }
 
 int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
@@ -10890,3 +11297,16 @@
 {
     return -ENOSYS;
 }
+
+int platform_get_controller_stream_from_params(struct str_parms *parms,
+                                               int *controller, int *stream) {
+    str_parms_get_int(parms, "controller", controller);
+    str_parms_get_int(parms, "stream", stream);
+    if (*controller < 0 || *controller >= MAX_CONTROLLERS ||
+            *stream < 0 || *stream >= MAX_STREAMS_PER_CONTROLLER) {
+        controller = 0;
+        stream = 0;
+        return -1;
+    }
+    return 0;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index a340427..2a570ce 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -111,7 +111,9 @@
     SND_DEVICE_OUT_HDMI,
     SND_DEVICE_OUT_SPEAKER_AND_HDMI,
     SND_DEVICE_OUT_DISPLAY_PORT,
+    SND_DEVICE_OUT_DISPLAY_PORT1,
     SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
+    SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT1,
     SND_DEVICE_OUT_BT_SCO,
     SND_DEVICE_OUT_BT_SCO_WB,
     SND_DEVICE_OUT_BT_SCO_SWB,
@@ -347,6 +349,7 @@
     SLIMBUS_6_RX = HEADPHONE_BACKEND,
     HDMI_RX_BACKEND,
     DISP_PORT_RX_BACKEND,
+    DISP_PORT1_RX_BACKEND,
     USB_AUDIO_RX_BACKEND,
     MAX_RX_CODEC_BACKENDS = USB_AUDIO_RX_BACKEND,
     /* TX BE follows RX BE */
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 30a10c5..bb8c558 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -48,6 +48,8 @@
     unsigned int   bit_width;
     bool           passthrough_enabled;
     audio_format_t format;
+    int controller;
+    int stream;
 };
 
 struct amp_db_and_gain_table {
@@ -389,4 +391,25 @@
                                     struct audio_custom_mtmx_in_params_info *info);
 int platform_add_custom_mtmx_in_params(void *platform,
                                     struct audio_custom_mtmx_in_params_info *info);
+
+int platform_get_edid_info_v2(void *platform, int controller, int stream);
+int platform_edid_get_max_channels_v2(void *platform, int controller, int stream);
+bool platform_is_edid_supported_format_v2(void *platform, int format,
+                                          int contoller, int stream);
+bool platform_is_edid_supported_sample_rate_v2(void *platform, int sample_rate,
+                                               int contoller, int stream);
+void platform_cache_edid_v2(void * platform, int controller, int stream);
+void platform_invalidate_hdmi_config_v2(void * platform, int controller, int stream);
+int platform_get_controller_stream_from_params(struct str_parms *parms,
+                                               int *controller, int *stream);
+int platform_set_ext_display_device_v2(void *platform, int controller, int stream);
+int platform_get_ext_disp_type_v2(void *platform, int controller, int stream);
+int platform_set_edid_channels_configuration_v2(void *platform, int channels,
+                                             int backend_idx, snd_device_t snd_device,
+                                             int controller, int stream);
+int platform_set_channel_allocation_v2(void *platform, int channel_alloc,
+                                             int controller, int stream);
+int platform_set_hdmi_channels_v2(void *platform, int channel_count,
+                                  int controller, int stream);
+int platform_get_display_port_ctl_index(int controller, int stream);
 #endif // AUDIO_PLATFORM_API_H