hal: enable audio over display port

Add support for audio over display port.

Change-Id: I3480d89c61ee5e5983715ec943fb02b1a9d5d151
diff --git a/hal/Android.mk b/hal/Android.mk
index 705e5e8..812ed99 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -310,6 +310,10 @@
     LOCAL_SHARED_LIBRARIES += libperipheral_client
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DISPLAY_PORT)),true)
+    LOCAL_CFLAGS += -DDISPLAY_PORT_ENABLED
+endif
+
 LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_COPY_HEADERS_TO   := mm-audio
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 569b4b2..65f516c 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -96,7 +96,7 @@
 * this is done when device switch happens by setting audioparamter
 */
 
-#define HDMI_PLUG_STATUS_NOTIFY_ENABLE 0x30
+#define EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE 0x30
 
 static ssize_t update_sysfs_node(const char *path, const char *data, size_t len)
 {
@@ -121,56 +121,60 @@
     return err;
 }
 
-static int get_hdmi_sysfs_node_index()
+static int get_ext_disp_sysfs_node_index(int ext_disp_type)
 {
-    static int node_index = -1;
+    int node_index = -1;
     char fbvalue[80] = {0};
     char fbpath[80] = {0};
     int i = 0;
-    FILE *hdmi_fp = NULL;
-
-    if(node_index >= 0) {
-        //hdmi sysfs node will not change so we just need to get the index once.
-        ALOGV("HDMI sysfs node is at fb%d", node_index);
-        return node_index;
-    }
+    FILE *ext_disp_fd = NULL;
 
     for(i = 0; i < 3; i++) {
         snprintf(fbpath, sizeof(fbpath),
                   "/sys/class/graphics/fb%d/msm_fb_type", i);
-        hdmi_fp = fopen(fbpath, "r");
-        if(hdmi_fp) {
-            fread(fbvalue, sizeof(char), 80, hdmi_fp);
-            if(strncmp(fbvalue, "dtv panel", strlen("dtv panel")) == 0) {
-                node_index = i;
-                ALOGV("HDMI is at fb%d",i);
-                fclose(hdmi_fp);
-                return node_index;
+        ext_disp_fd = fopen(fbpath, "r");
+        if (ext_disp_fd) {
+            if (fread(fbvalue, sizeof(char), 80, ext_disp_fd)) {
+                if(((strncmp(fbvalue, "dtv panel", strlen("dtv panel")) == 0) &&
+                    (ext_disp_type == EXT_DISPLAY_TYPE_HDMI)) ||
+                   ((strncmp(fbvalue, "dp panel", strlen("dp panel")) == 0) &&
+                    (ext_disp_type == EXT_DISPLAY_TYPE_DP))) {
+                    node_index = i;
+                    ALOGD("%s: Ext Disp:%d is at fb%d", __func__, ext_disp_type, i);
+                    fclose(ext_disp_fd);
+                    return node_index;
+                }
             }
-            fclose(hdmi_fp);
+            fclose(ext_disp_fd);
         } else {
-            ALOGE("Failed to open fb node %d",i);
+            ALOGE("%s: Failed to open fb node %d", __func__, i);
         }
     }
 
     return -1;
 }
 
-static int update_hdmi_sysfs_node(int node_value)
+static int update_ext_disp_sysfs_node(const struct audio_device *adev, int node_value)
 {
-    char hdmi_ack_path[80] = {0};
-    char hdmi_ack_value[3] = {0};
+    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);
 
-    index = get_hdmi_sysfs_node_index();
+    if (ext_disp_type < 0) {
+        ALOGE("%s, Unable to get the external display type, err:%d",
+              __func__, ext_disp_type);
+        return -EINVAL;
+    }
 
+    index = get_ext_disp_sysfs_node_index(ext_disp_type);
     if (index >= 0) {
-        snprintf(hdmi_ack_value, sizeof(hdmi_ack_value), "%d", node_value);
-        snprintf(hdmi_ack_path, sizeof(hdmi_ack_path),
+        snprintf(ext_disp_ack_value, sizeof(ext_disp_ack_value), "%d", node_value);
+        snprintf(ext_disp_ack_path, sizeof(ext_disp_ack_path),
                   "/sys/class/graphics/fb%d/hdmi_audio_cb", index);
 
-        ret = update_sysfs_node(hdmi_ack_path, hdmi_ack_value,
-                sizeof(hdmi_ack_value));
+        ret = update_sysfs_node(ext_disp_ack_path, ext_disp_ack_value,
+                sizeof(ext_disp_ack_value));
 
         ALOGI("update hdmi_audio_cb at fb[%d] to:[%d] %s",
             index, node_value, (ret >= 0) ? "success":"fail");
@@ -179,25 +183,27 @@
     return ret;
 }
 
-static void check_and_set_hdmi_connection_status(struct str_parms *parms)
+static void check_and_set_ext_disp_connection_status(const struct audio_device *adev,
+                                                     struct str_parms *parms)
 {
     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_HDMI)) {
-        //params = "connect=1024" for HDMI connection.
+            && (atoi(value) & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+        //params = "connect=1024" for external display connection.
         if (is_hdmi_sysfs_node_init == false) {
+            //check if this is different for dp and hdmi
             is_hdmi_sysfs_node_init = true;
-            update_hdmi_sysfs_node(HDMI_PLUG_STATUS_NOTIFY_ENABLE);
+            update_ext_disp_sysfs_node(adev, EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE);
         }
-        update_hdmi_sysfs_node(1);
+        update_ext_disp_sysfs_node(adev, 1);
     } else if(str_parms_get_str(parms, "disconnect", value, sizeof(value)) >= 0
-            && (atoi(value) & AUDIO_DEVICE_OUT_HDMI)){
-        //params = "disconnect=1024" for HDMI disconnection.
-        update_hdmi_sysfs_node(0);
+            && (atoi(value) & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
+        //params = "disconnect=1024" for external display disconnection.
+        update_ext_disp_sysfs_node(adev, 0);
     } else {
-        // handle hdmi devices only
+        // handle ext disp devices only
         return;
     }
 }
@@ -764,7 +770,7 @@
    audio_extn_source_track_set_parameters(adev, parms);
    audio_extn_fbsp_set_parameters(parms);
    audio_extn_keep_alive_set_parameters(adev, parms);
-   check_and_set_hdmi_connection_status(parms);
+   check_and_set_ext_disp_connection_status(adev, parms);
    if (adev->offload_effects_set_parameters != NULL)
        adev->offload_effects_set_parameters(parms);
 }
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e8caeee..1d5b12e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -407,6 +407,12 @@
 #define AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH  0x10000
 #endif
 
+enum {
+    EXT_DISPLAY_TYPE_NONE,
+    EXT_DISPLAY_TYPE_HDMI,
+    EXT_DISPLAY_TYPE_DP
+};
+
 #ifndef HDMI_PASSTHROUGH_ENABLED
 #define audio_extn_passthru_update_stream_configuration(adev, out)            (0)
 #define audio_extn_passthru_is_convert_supported(adev, out)                   (0)
diff --git a/hal/audio_extn/keep_alive.c b/hal/audio_extn/keep_alive.c
index 60e7eef..1df6d08 100644
--- a/hal/audio_extn/keep_alive.c
+++ b/hal/audio_extn/keep_alive.c
@@ -36,8 +36,6 @@
 #include "platform_api.h"
 #include <platform.h>
 
-#define SILENCE_MIXER_PATH "silence-playback hdmi"
-#define SILENCE_DEV_ID 32           /* index into machine driver */
 #define SILENCE_INTERVAL 2 /*In secs*/
 
 typedef enum {
@@ -131,11 +129,14 @@
     if (ka.pcm)
         return -EEXIST;
 
-    ALOGD("opening silence device %d", SILENCE_DEV_ID);
+    int silence_pcm_dev_id = platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
+                                                        PCM_PLAYBACK);
+
+    ALOGD("opening silence device %d", silence_pcm_dev_id);
     struct audio_device * adev = (struct audio_device *)ka.userdata;
-    ka.pcm = pcm_open(adev->snd_card, SILENCE_DEV_ID,
+    ka.pcm = pcm_open(adev->snd_card, silence_pcm_dev_id,
                       flags, &silence_config);
-    ALOGD("opened silence device %d", SILENCE_DEV_ID);
+    ALOGD("opened silence device %d", silence_pcm_dev_id);
     if (ka.pcm == NULL || !pcm_is_ready(ka.pcm)) {
         ALOGE("%s: %s", __func__, pcm_get_error(ka.pcm));
         if (ka.pcm != NULL) {
@@ -208,8 +209,10 @@
     ka.done = false;
 
     /*configure app type */
+    int silence_pcm_dev_id = platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
+                                                        PCM_PLAYBACK);
     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
-             "Audio Stream %d App Type Cfg",SILENCE_DEV_ID);
+             "Audio Stream %d App Type Cfg", silence_pcm_dev_id);
 
     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
     if (!ctl) {
@@ -219,7 +222,28 @@
         goto exit;
     }
 
-    snd_device = SND_DEVICE_OUT_HDMI;
+    /* Configure HDMI/DP Backend with default values, this as well
+     * helps reconfigure HDMI/DP backend after passthrough.
+     */
+    int ext_disp_type = platform_get_ext_disp_type(adev->platform);
+    switch(ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            snd_device = SND_DEVICE_OUT_HDMI;
+            set_mixer_control(adev->mixer, "HDMI RX Format", "LPCM");
+            set_mixer_control(adev->mixer, "HDMI_RX SampleRate", "KHZ_48");
+            set_mixer_control(adev->mixer, "HDMI_RX Channels", "Two");
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+            set_mixer_control(adev->mixer, "Display Port Format", "LPCM");
+            set_mixer_control(adev->mixer, "Display Port RX SampleRate", "KHZ_48");
+            set_mixer_control(adev->mixer, "Display Port RX Channels", "Two");
+            break;
+        default:
+            ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
+            goto exit;
+    }
+
     acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
     if (acdb_dev_id < 0) {
         ALOGE("%s: Couldn't get the acdb dev id", __func__);
@@ -237,23 +261,27 @@
           platform_get_default_app_type(adev->platform),
           acdb_dev_id, sample_rate);
     mixer_ctl_set_array(ctl, app_type_cfg, len);
-    /*Configure HDMI Backend with default values, this as well
-     *helps reconfigure HDMI backend after passthrough
-     */
-    set_mixer_control(adev->mixer, "HDMI RX Format", "LPCM");
-    set_mixer_control(adev->mixer, "HDMI_RX SampleRate", "KHZ_48");
-    set_mixer_control(adev->mixer, "HDMI_RX Channels", "Two");
 
     /*send calibration*/
     usecase = calloc(1, sizeof(struct audio_usecase));
     usecase->type = PCM_PLAYBACK;
-    usecase->out_snd_device = SND_DEVICE_OUT_HDMI;
+    usecase->out_snd_device = snd_device;
 
     platform_send_audio_calibration(adev->platform, usecase,
                 platform_get_default_app_type(adev->platform), sample_rate);
 
     /*apply audio route */
-    audio_route_apply_and_update_path(adev->audio_route, SILENCE_MIXER_PATH);
+    switch(ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            audio_route_apply_and_update_path(adev->audio_route, "silence-playback hdmi");
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            audio_route_apply_and_update_path(adev->audio_route, "silence-playback display-port");
+            break;
+        default:
+            ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
+            goto exit;
+    }
 
     if (open_silence_stream() == 0) {
         send_cmd_l(REQUEST_WRITE);
@@ -284,7 +312,19 @@
         pthread_cond_wait(&ka.cond, &ka.lock);
     }
     close_silence_stream();
-    audio_route_reset_and_update_path(adev->audio_route, SILENCE_MIXER_PATH);
+
+    /*apply audio route */
+    int ext_disp_type = platform_get_ext_disp_type(adev->platform);
+    switch(ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            audio_route_reset_and_update_path(adev->audio_route, "silence-playback hdmi");
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            audio_route_reset_and_update_path(adev->audio_route, "silence-playback display-port");
+            break;
+        default:
+            ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
+    }
 
 exit:
     pthread_mutex_unlock(&ka.lock);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1215d2d..ee7647e 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -255,6 +255,7 @@
 
     [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
     [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
+    [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
 };
 
 static const audio_usecase_t offload_usecases[] = {
@@ -849,7 +850,7 @@
         if (SND_DEVICE_OUT_BT_A2DP == snd_device)
             audio_extn_a2dp_stop_playback();
 
-        if (snd_device == SND_DEVICE_OUT_HDMI)
+        if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
             adev->is_channel_status_set = false;
         else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
                  adev->native_playback_enabled) {
@@ -1084,6 +1085,13 @@
 
     reset_hdmi_sink_caps(out);
 
+    /* Cache ext disp type */
+    ret = platform_get_ext_disp_type(adev->platform);
+    if (ret < 0) {
+        ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
+        return ret;
+    }
+
     switch (channels) {
     case 8:
         ALOGV("%s: HDMI supports 7.1 channels", __func__);
@@ -4108,7 +4116,12 @@
     if (ret >= 0) {
         val = atoi(value);
         if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
-            ALOGV("cache new edid");
+            ALOGV("cache new ext disp type and edid");
+            ret = platform_get_ext_disp_type(adev->platform);
+            if (ret < 0) {
+                ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
+                return ret;
+            }
             platform_cache_edid(adev->platform);
         } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
                    !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 664d1fc..c1797bd 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -146,6 +146,8 @@
     USECASE_AUDIO_PLAYBACK_AFE_PROXY,
     USECASE_AUDIO_RECORD_AFE_PROXY,
 
+    USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
+
     AUDIO_USECASE_MAX
 };
 
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 6309ce2..7fe114b 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -68,7 +68,6 @@
 #define PLATFORM_INFO_XML_PATH_EXTCODEC  "/system/etc/audio_platform_info_extcodec.xml"
 
 #define LIB_ACDB_LOADER "libacdbloader.so"
-#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
 #define CVD_VERSION_MIXER_CTL "CVD Version"
 
 #define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
@@ -243,6 +242,7 @@
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
+    int ext_disp_type;
     codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
     codec_backend_cfg_t current_tx_backend_cfg[MAX_CODEC_TX_BACKENDS];
     char ec_ref_mixer_path[64];
@@ -318,6 +318,7 @@
                                           AFE_PROXY_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
                                         AFE_PROXY_RECORD_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = {MULTIMEDIA9_PCM_DEVICE, -1},
 };
 
 /* Array to store sound devices */
@@ -346,6 +347,8 @@
     [SND_DEVICE_OUT_VOICE_LINE] = "voice-line",
     [SND_DEVICE_OUT_HDMI] = "hdmi",
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
+    [SND_DEVICE_OUT_DISPLAY_PORT] = "display-port",
+    [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = "speaker-and-display-port",
     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
     [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
     [SND_DEVICE_OUT_BT_A2DP] = "bt-a2dp",
@@ -467,6 +470,8 @@
     [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
     [SND_DEVICE_OUT_HDMI] = 18,
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
+    [SND_DEVICE_OUT_DISPLAY_PORT] = 18,
+    [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = 14,
     [SND_DEVICE_OUT_BT_SCO] = 22,
     [SND_DEVICE_OUT_BT_SCO_WB] = 39,
     [SND_DEVICE_OUT_BT_A2DP] = 20,
@@ -590,6 +595,8 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_LINE)},
     {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_SPEAKER_AND_DISPLAY_PORT)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_A2DP)},
@@ -712,6 +719,7 @@
     {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
     {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
     {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE)},
 };
 
 #define NO_COLS 2
@@ -1203,6 +1211,8 @@
     backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
     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_SPEAKER_AND_DISPLAY_PORT] = strdup("speaker-and-display-port");
     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");
@@ -1219,6 +1229,8 @@
 
     hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI_RX");
+    hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT_RX");
+    hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT_RX");
     hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
 
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
@@ -1672,6 +1684,7 @@
     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;
 
@@ -1932,6 +1945,13 @@
     my_data->current_backend_cfg[HDMI_RX_BACKEND].channels_mixer_ctl =
         strdup("HDMI_RX Channels");
 
+    my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("Display Port RX Bit Format");
+    my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].samplerate_mixer_ctl =
+        strdup("Display Port RX SampleRate");
+    my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels_mixer_ctl =
+        strdup("Display Port RX Channels");
+
     ret = audio_extn_utils_get_codec_version(snd_card_name,
                                              my_data->adev->snd_card,
                                              my_data->codec_version);
@@ -2462,6 +2482,8 @@
                         port = HEADPHONE_BACKEND;
                 else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
                         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], "usb-headphones") == 0)
                         port = USB_AUDIO_RX_BACKEND;
         }
@@ -2824,6 +2846,19 @@
 
         new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
         status = true;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_DISPLAY_PORT)) {
+        *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_PORT;
+        status = true;
     } 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;
@@ -2842,6 +2877,42 @@
     return status;
 }
 
+int platform_get_ext_disp_type(void *platform)
+{
+    int disp_type;
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->ext_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;
+    }
+
+#ifdef DISPLAY_PORT_ENABLED
+    struct audio_device *adev = my_data->adev;
+    struct mixer_ctl *ctl;
+    char *mixer_ctl_name = "External Display Type";
+
+    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;
+    }
+
+    disp_type = mixer_ctl_get_value(ctl, 0);
+    if (disp_type == EXT_DISPLAY_TYPE_NONE) {
+         ALOGE("%s: Invalid external display type: %d", __func__, disp_type);
+         return -EINVAL;
+    }
+#else
+    disp_type = EXT_DISPLAY_TYPE_HDMI;
+#endif
+    my_data->ext_disp_type = disp_type;
+    ALOGD("%s: ext disp type:%s", __func__, (disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+    return disp_type;
+}
+
 snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -2899,7 +2970,17 @@
                 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
         } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
-            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+            switch(my_data->ext_disp_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;
+                     break;
+                default:
+                     ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+                     goto exit;
+            }
         } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
             snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
@@ -3043,7 +3124,17 @@
         else
             snd_device = SND_DEVICE_OUT_BT_SCO;
     } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
-        snd_device = SND_DEVICE_OUT_HDMI ;
+            switch(my_data->ext_disp_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;
+                    break;
+                default:
+                     ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+                     goto exit;
+            }
     } else if (devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
         snd_device = SND_DEVICE_OUT_BT_A2DP;
     } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
@@ -3468,7 +3559,7 @@
     struct audio_device *adev = my_data->adev;
     struct mixer_ctl *ctl;
     const char *channel_cnt_str = NULL;
-    const char *mixer_ctl_name = "HDMI_RX Channels";
+    char *mixer_ctl_name;
     switch (channel_count) {
     case 8:
         channel_cnt_str = "Eight"; break;
@@ -3485,13 +3576,25 @@
     default:
         channel_cnt_str = "Two"; break;
     }
+
+    switch(my_data->ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            mixer_ctl_name = "HDMI_RX Channels";
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            mixer_ctl_name = "Display Port RX Channels";
+            break;
+        default:
+            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            return -EINVAL;
+    }
     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("HDMI channel count: %s", channel_cnt_str);
+    ALOGV("Ext disp channel count: %s", channel_cnt_str);
     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
     return 0;
 }
@@ -4162,7 +4265,7 @@
             mixer_ctl_set_enum_by_string(ctl, rate_str);
             my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
     }
-    if ((backend_idx == HDMI_RX_BACKEND) &&
+    if ((backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) &&
         (channels != my_data->current_backend_cfg[backend_idx].channels)) {
         struct  mixer_ctl *ctl;
         char *channel_cnt_str = NULL;
@@ -4199,22 +4302,32 @@
                my_data->current_backend_cfg[backend_idx].channels_mixer_ctl, channel_cnt_str);
     }
 
-    if (backend_idx == HDMI_RX_BACKEND) {
-        const char *hdmi_format_ctrl = "HDMI RX Format";
-        struct mixer_ctl *ctl;
-        ctl = mixer_get_ctl_by_name(adev->mixer,hdmi_format_ctrl);
+    bool set_ext_disp_format = false;
+    char *ext_disp_format = NULL;
 
+    if (backend_idx == HDMI_RX_BACKEND) {
+        ext_disp_format = "HDMI RX Format";
+        set_ext_disp_format = true;
+    } else if (backend_idx == DISP_PORT_RX_BACKEND) {
+        ext_disp_format = "Display Port Rx Format";
+        set_ext_disp_format = true;
+    } else {
+        ALOGV("%s: Format doesnt have to be set", __func__);
+    }
+
+    if (set_ext_disp_format) {
+        struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, ext_disp_format);
         if (!ctl) {
             ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
-                   __func__, hdmi_format_ctrl);
+                   __func__, ext_disp_format);
             return -EINVAL;
         }
 
         if (passthrough_enabled) {
-            ALOGD("%s:HDMI compress format", __func__);
+            ALOGD("%s:Ext display compress format", __func__);
             mixer_ctl_set_enum_by_string(ctl, "Compr");
         } else {
-            ALOGD("%s: HDMI PCM format", __func__);
+            ALOGD("%s: Ext display PCM format", __func__);
             mixer_ctl_set_enum_by_string(ctl, "LPCM");
         }
     }
@@ -4228,6 +4341,7 @@
  */
 static void platform_check_hdmi_backend_cfg(struct audio_device* adev,
                                    struct audio_usecase* usecase,
+                                   int backend_idx,
                                    struct audio_backend_cfg *hdmi_backend_cfg)
 {
     unsigned int bit_width;
@@ -4261,13 +4375,13 @@
         //Check EDID info for supported samplerate
         if (!edid_is_supported_sr(edid_info,sample_rate)) {
             //reset to current sample rate
-            sample_rate = my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate;
+            sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
         }
 
         //Check EDID info for supported bit width
         if (!edid_is_supported_bps(edid_info,bit_width)) {
             //reset to current sample rate
-            bit_width = my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width;
+            bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
         }
 
         if (channels > max_supported_channels)
@@ -4430,7 +4544,7 @@
         hdmi_backend_cfg.channels = channels;
         hdmi_backend_cfg.passthrough_enabled = false;
 
-        platform_check_hdmi_backend_cfg(adev, usecase, &hdmi_backend_cfg);
+        platform_check_hdmi_backend_cfg(adev, usecase, backend_idx, &hdmi_backend_cfg);
 
         bit_width = hdmi_backend_cfg.bit_width;
         sample_rate = hdmi_backend_cfg.sample_rate;
@@ -4879,7 +4993,7 @@
     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;
@@ -4889,17 +5003,28 @@
         return 0;
     }
 
+    switch(my_data->ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            mix_ctl_name = "HDMI EDID";
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            mix_ctl_name = "Display Port EDID";
+            break;
+        default:
+            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            return -EINVAL;
+    }
+
     if (my_data->edid_info == NULL) {
         my_data->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, AUDIO_DATA_BLOCK_MIXER_CTL);
+    ctl = mixer_get_ctl_by_name(adev->mixer, mix_ctl_name);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
-              __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
+              __func__, mix_ctl_name);
         goto fail;
     }
 
@@ -4918,8 +5043,9 @@
     }
     edid_data[0] = count;
     memcpy(&edid_data[1], block, count);
+
     if (!edid_get_sink_caps(info, edid_data)) {
-        ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
+        ALOGE("%s: Failed to get extn disp sink capabilities", __func__);
         goto fail;
     }
     my_data->edid_valid = true;
@@ -4938,16 +5064,28 @@
 int platform_set_channel_allocation(void *platform, int channel_alloc)
 {
     struct mixer_ctl *ctl;
-    const char *mixer_ctl_name = "HDMI RX CA";
+    char *mixer_ctl_name;
     int ret;
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
 
+    switch(my_data->ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            mixer_ctl_name = "HDMI RX CA";
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            mixer_ctl_name = "Display Port RX CA";
+            break;
+        default:
+            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            return -EINVAL;
+    }
+
     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);
-        ret = EINVAL;
+        return -EINVAL;
     }
     ALOGD(":%s channel allocation = 0x%x", __func__, channel_alloc);
     ret = mixer_ctl_set_value(ctl, 0, channel_alloc);
@@ -4962,7 +5100,7 @@
 int platform_set_channel_map(void *platform, int ch_count, char *ch_map, int snd_id)
 {
     struct mixer_ctl *ctl;
-    char mixer_ctl_name[44]; // max length of name is 44 as defined
+    char mixer_ctl_name[44] = {0}; // max length of name is 44 as defined
     int ret;
     unsigned int i;
     int set_values[8] = {0};
@@ -5178,16 +5316,25 @@
 
 void platform_invalidate_hdmi_config(void * platform)
 {
+    //reset ext display EDID info
     struct platform_data *my_data = (struct platform_data *)platform;
     my_data->edid_valid = false;
     if (my_data->edid_info) {
         memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
     }
 
-    //reset HDMI_RX_BACKEND to default values
-    my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-    my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
-    my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+    if (my_data->ext_disp_type == EXT_DISPLAY_TYPE_HDMI) {
+        //reset HDMI_RX_BACKEND to default values
+        my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+        my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+    } else {
+        //reset Display port BACKEND to default values
+        my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+        my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+    }
+    my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
 }
 
 int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 6c89d0a..516a298 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -96,6 +96,8 @@
     SND_DEVICE_OUT_VOICE_LINE,
     SND_DEVICE_OUT_HDMI,
     SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+    SND_DEVICE_OUT_DISPLAY_PORT,
+    SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
     SND_DEVICE_OUT_BT_SCO,
     SND_DEVICE_OUT_BT_SCO_WB,
     SND_DEVICE_OUT_BT_A2DP,
@@ -218,6 +220,7 @@
     HEADPHONE_BACKEND,
     SLIMBUS_6_RX = HEADPHONE_BACKEND,
     HDMI_RX_BACKEND,
+    DISP_PORT_RX_BACKEND,
     USB_AUDIO_RX_BACKEND,
     MAX_CODEC_BACKENDS
 };
@@ -281,6 +284,7 @@
 #define AUDIO_RECORD_PCM_DEVICE 0
 #define MULTIMEDIA2_PCM_DEVICE 1
 #define MULTIMEDIA3_PCM_DEVICE 4
+#define MULTIMEDIA9_PCM_DEVICE 32
 #define FM_PLAYBACK_PCM_DEVICE 5
 #define FM_CAPTURE_PCM_DEVICE  6
 #define HFP_PCM_RX 5
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index e5d42bd..f3c4d28 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -667,6 +667,11 @@
     return -ENOSYS;
 }
 
+int platform_get_ext_disp_type(void *platform)
+{
+    return EXT_DISPLAY_TYPE_HDMI;
+}
+
 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 07060b6..c9ac74a 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -63,6 +63,8 @@
     SND_DEVICE_OUT_VOICE_HEADPHONES,
     SND_DEVICE_OUT_HDMI,
     SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+    SND_DEVICE_OUT_DISPLAY_PORT,
+    SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
     SND_DEVICE_OUT_BT_SCO,
     SND_DEVICE_OUT_BT_A2DP,
     SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 24bee89..ff062b6 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -57,7 +57,6 @@
 #include <linux/msm_audio.h>
 
 #define LIB_ACDB_LOADER "libacdbloader.so"
-#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
 #define CVD_VERSION_MIXER_CTL "CVD Version"
 
 #define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
@@ -237,6 +236,7 @@
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
+    int ext_disp_type;
     char ec_ref_mixer_path[64];
     codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
     codec_backend_cfg_t current_tx_backend_cfg[MAX_CODEC_TX_BACKENDS];
@@ -322,6 +322,7 @@
                                           AFE_PROXY_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
                                         AFE_PROXY_RECORD_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = {MULTIMEDIA9_PCM_DEVICE, -1},
 
 };
 
@@ -350,6 +351,8 @@
     [SND_DEVICE_OUT_VOICE_LINE] = "voice-line",
     [SND_DEVICE_OUT_HDMI] = "hdmi",
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
+    [SND_DEVICE_OUT_DISPLAY_PORT] = "display-port",
+    [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = "speaker-and-display-port",
     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
     [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
     [SND_DEVICE_OUT_BT_A2DP] = "bt-a2dp",
@@ -467,6 +470,8 @@
     [SND_DEVICE_OUT_VOICE_LINE] = 10,
     [SND_DEVICE_OUT_HDMI] = 18,
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
+    [SND_DEVICE_OUT_DISPLAY_PORT] = 18,
+    [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = 14,
     [SND_DEVICE_OUT_BT_SCO] = 22,
     [SND_DEVICE_OUT_BT_SCO_WB] = 39,
     [SND_DEVICE_OUT_BT_A2DP] = 20,
@@ -586,6 +591,8 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_LINE)},
     {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_SPEAKER_AND_DISPLAY_PORT)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_A2DP)},
@@ -707,6 +714,7 @@
     {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE)},
 };
 
 #define NO_COLS 2
@@ -1098,6 +1106,8 @@
     backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
     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_SPEAKER_AND_DISPLAY_PORT] = strdup("speaker-and-display-port");
     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");
@@ -1117,6 +1127,8 @@
     hw_interface_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("SLIMBUS_5_RX");
     hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI_RX");
+    hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT_RX");
+    hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT_RX");
     hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
 
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
@@ -1527,6 +1539,7 @@
     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->hw_dep_fd = -1;
 
     property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
@@ -1774,6 +1787,12 @@
         strdup("HDMI_RX SampleRate");
     my_data->current_backend_cfg[HDMI_RX_BACKEND].channels_mixer_ctl =
         strdup("HDMI_RX Channels");
+    my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bitwidth_mixer_ctl =
+        strdup("Display Port RX Bit Format");
+    my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].samplerate_mixer_ctl =
+        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[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
         strdup("USB_AUDIO_RX Format");
@@ -2315,6 +2334,8 @@
                         port = HEADPHONE_BACKEND;
                 else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
                         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], "usb-headphones") == 0)
                         port = USB_AUDIO_RX_BACKEND;
         }
@@ -2672,6 +2693,12 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
         status = true;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_DISPLAY_PORT)) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+        new_snd_devices[1] = SND_DEVICE_OUT_DISPLAY_PORT;
+        status = true;
     } 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;
@@ -2691,6 +2718,43 @@
     return status;
 }
 
+int platform_get_ext_disp_type(void *platform)
+{
+    int disp_type;
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->ext_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;
+    }
+
+#ifdef DISPLAY_PORT_ENABLED
+    struct audio_device *adev = my_data->adev;
+    struct mixer_ctl *ctl;
+    char *mixer_ctl_name = "External Display Type";
+
+    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;
+    }
+
+    disp_type = mixer_ctl_get_value(ctl, 0);
+    if (disp_type == EXT_DISPLAY_TYPE_NONE) {
+         ALOGE("%s: Invalid external display type: %d", __func__, disp_type);
+         return -EINVAL;
+    }
+#else
+    disp_type = EXT_DISPLAY_TYPE_HDMI;
+#endif
+
+    my_data->ext_disp_type = disp_type;
+    ALOGD("%s: ext disp type:%s", __func__, (disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+    return disp_type;
+}
+
 snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -2736,7 +2800,17 @@
             snd_device = SND_DEVICE_OUT_SPEAKER_AND_LINE;
         } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
-            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+            switch(my_data->ext_disp_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;
+                    break;
+                default:
+                    ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+                    goto exit;
+            }
         } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
                                AUDIO_DEVICE_OUT_SPEAKER)) {
             snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
@@ -2861,7 +2935,17 @@
     } else if (devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
         snd_device = SND_DEVICE_OUT_BT_A2DP;
     } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
-        snd_device = SND_DEVICE_OUT_HDMI ;
+            switch(my_data->ext_disp_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;
+                    break;
+                default:
+                    ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+                    goto exit;
+            }
     } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
                devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
         ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
@@ -3267,7 +3351,7 @@
     struct audio_device *adev = my_data->adev;
     struct mixer_ctl *ctl;
     const char *channel_cnt_str = NULL;
-    const char *mixer_ctl_name = "HDMI_RX Channels";
+    char *mixer_ctl_name;
     switch (channel_count) {
     case 8:
         channel_cnt_str = "Eight"; break;
@@ -3284,13 +3368,26 @@
     default:
         channel_cnt_str = "Two"; break;
     }
+
+    switch(my_data->ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            mixer_ctl_name = "HDMI_RX Channels";
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            mixer_ctl_name = "Display Port RX Channels";
+            break;
+        default:
+            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            return -EINVAL;
+    }
+
     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("HDMI channel count: %s", channel_cnt_str);
+    ALOGV("Ext disp channel count: %s", channel_cnt_str);
     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
     return 0;
 }
@@ -4199,7 +4296,7 @@
             mixer_ctl_set_enum_by_string(ctl, rate_str);
             my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
     }
-    if ((backend_idx == HDMI_RX_BACKEND) &&
+    if ((backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) &&
         (channels != my_data->current_backend_cfg[backend_idx].channels)) {
         struct  mixer_ctl *ctl;
         char *channel_cnt_str = NULL;
@@ -4236,22 +4333,32 @@
                my_data->current_backend_cfg[backend_idx].channels_mixer_ctl, channel_cnt_str);
     }
 
-    if (backend_idx == HDMI_RX_BACKEND) {
-        const char *hdmi_format_ctrl = "HDMI RX Format";
-        struct mixer_ctl *ctl;
-        ctl = mixer_get_ctl_by_name(adev->mixer,hdmi_format_ctrl);
+    bool set_ext_disp_format = false;
+    char *ext_disp_format = NULL;
 
+    if (backend_idx == HDMI_RX_BACKEND) {
+        ext_disp_format = "HDMI RX Format";
+        set_ext_disp_format = true;
+    } else if (backend_idx == DISP_PORT_RX_BACKEND) {
+        ext_disp_format = "Display Port Rx Format";
+        set_ext_disp_format = true;
+    } else {
+        ALOGV("%s: Format doesnt have to be set", __func__);
+    }
+
+    if (set_ext_disp_format) {
+        struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, ext_disp_format);
         if (!ctl) {
             ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
-                   __func__, hdmi_format_ctrl);
+                  __func__, ext_disp_format);
             return -EINVAL;
         }
 
         if (passthrough_enabled) {
-            ALOGD("%s:HDMI compress format", __func__);
+            ALOGD("%s:Ext display compress format", __func__);
             mixer_ctl_set_enum_by_string(ctl, "Compr");
         } else {
-            ALOGD("%s: HDMI PCM format", __func__);
+            ALOGD("%s: Ext display PCM format", __func__);
             mixer_ctl_set_enum_by_string(ctl, "LPCM");
         }
     }
@@ -4276,6 +4383,7 @@
  */
 static void platform_check_hdmi_backend_cfg(struct audio_device* adev,
                                    struct audio_usecase* usecase,
+                                   int backend_idx,
                                    struct audio_backend_cfg *hdmi_backend_cfg)
 {
     unsigned int bit_width;
@@ -4309,13 +4417,13 @@
         //Check EDID info for supported samplerate
         if (!edid_is_supported_sr(edid_info,sample_rate)) {
             //reset to current sample rate
-            sample_rate = my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate;
+            sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
         }
 
         //Check EDID info for supported bit width
         if (!edid_is_supported_bps(edid_info,bit_width)) {
             //reset to current sample rate
-            bit_width = my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width;
+            bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
         }
 
         if (channels > max_supported_channels)
@@ -4469,14 +4577,14 @@
                    __func__, bit_width, sample_rate, channels);
     }
 
-    if (backend_idx == HDMI_RX_BACKEND) {
+    if (backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) {
         struct audio_backend_cfg hdmi_backend_cfg;
         hdmi_backend_cfg.bit_width = bit_width;
         hdmi_backend_cfg.sample_rate = sample_rate;
         hdmi_backend_cfg.channels = channels;
         hdmi_backend_cfg.passthrough_enabled = false;
 
-        platform_check_hdmi_backend_cfg(adev, usecase, &hdmi_backend_cfg);
+        platform_check_hdmi_backend_cfg(adev, usecase, backend_idx, &hdmi_backend_cfg);
 
         bit_width = hdmi_backend_cfg.bit_width;
         sample_rate = hdmi_backend_cfg.sample_rate;
@@ -4927,7 +5035,7 @@
     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;
@@ -4937,17 +5045,28 @@
         return 0;
     }
 
+    switch(my_data->ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            mix_ctl_name = "HDMI EDID";
+            break;
+        case EXT_DISPLAY_TYPE_DP:
+            mix_ctl_name = "Display Port EDID";
+            break;
+        default:
+            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            return -EINVAL;
+    }
+
     if (my_data->edid_info == NULL) {
         my_data->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, AUDIO_DATA_BLOCK_MIXER_CTL);
+    ctl = mixer_get_ctl_by_name(adev->mixer, mix_ctl_name);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
-              __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
+              __func__, mix_ctl_name);
         goto fail;
     }
 
@@ -4968,7 +5087,7 @@
     memcpy(&edid_data[1], block, count);
 
     if (!edid_get_sink_caps(info, edid_data)) {
-        ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
+        ALOGE("%s: Failed to get extn disp sink capabilities", __func__);
         goto fail;
     }
     my_data->edid_valid = true;
@@ -4987,16 +5106,28 @@
 int platform_set_channel_allocation(void *platform, int channel_alloc)
 {
     struct mixer_ctl *ctl;
-    const char *mixer_ctl_name = "HDMI RX CA";
+    char *mixer_ctl_name;
     int ret;
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
 
+    switch(my_data->ext_disp_type) {
+        case EXT_DISPLAY_TYPE_HDMI:
+            mixer_ctl_name = "HDMI RX CA";
+        break;
+        case EXT_DISPLAY_TYPE_DP:
+            mixer_ctl_name = "Display Port RX CA";
+            break;
+        default:
+            ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+            return -EINVAL;
+    }
+
     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);
-        ret = EINVAL;
+        return -EINVAL;
     }
     ALOGD(":%s channel allocation = 0x%x", __func__, channel_alloc);
     ret = mixer_ctl_set_value(ctl, 0, channel_alloc);
@@ -5228,17 +5359,25 @@
 
 void platform_invalidate_hdmi_config(void * platform)
 {
-    //reset HDMI EDID info
+    //reset ext display EDID info
     struct platform_data *my_data = (struct platform_data *)platform;
     my_data->edid_valid = false;
     if (my_data->edid_info) {
         memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
     }
 
-    //reset HDMI_RX_BACKEND to default values
-    my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-    my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
-    my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+    if (my_data->ext_disp_type == EXT_DISPLAY_TYPE_HDMI) {
+        //reset HDMI_RX_BACKEND to default values
+        my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+        my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+    } else {
+        //reset Display port BACKEND to default values
+        my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+        my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+    }
+    my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
 }
 
 int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9394ef8..9b8c01b 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -93,6 +93,8 @@
     SND_DEVICE_OUT_VOICE_LINE,
     SND_DEVICE_OUT_HDMI,
     SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+    SND_DEVICE_OUT_DISPLAY_PORT,
+    SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
     SND_DEVICE_OUT_BT_SCO,
     SND_DEVICE_OUT_BT_SCO_WB,
     SND_DEVICE_OUT_BT_A2DP,
@@ -210,6 +212,7 @@
     HEADPHONE_BACKEND,
     SLIMBUS_6_RX = HEADPHONE_BACKEND,
     HDMI_RX_BACKEND,
+    DISP_PORT_RX_BACKEND,
     USB_AUDIO_RX_BACKEND,
     MAX_CODEC_BACKENDS
 };
@@ -273,6 +276,7 @@
 #define AUDIO_RECORD_PCM_DEVICE 0
 #define MULTIMEDIA2_PCM_DEVICE 1
 #define MULTIMEDIA3_PCM_DEVICE 4
+#define MULTIMEDIA9_PCM_DEVICE 32
 #define FM_PLAYBACK_PCM_DEVICE 5
 #define FM_CAPTURE_PCM_DEVICE  6
 #define HFP_PCM_RX 5
diff --git a/hal/platform_api.h b/hal/platform_api.h
index ec64206..25ff64c 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -158,4 +158,5 @@
 bool platform_check_codec_dsd_support(void *platform);
 bool platform_check_codec_asrc_support(void *platform);
 int platform_get_backend_index(snd_device_t snd_device);
+int platform_get_ext_disp_type(void *platform);
 #endif // AUDIO_PLATFORM_API_H