hal: Dolby trumpet security changes

- ip-handler interface audio extension module changes to
  handle ADSP trumpet  security mechanism.
- Send the library ion fd to driver to assign the corresponding
  memory to DSP for decryption of the decoder library.
- adsp handler changes to handle COPP events from ADSP

Change-Id: I4e7628111bd482faa98c6d3ba9453d22c9dad755
diff --git a/hal/audio_extn/adsp_hdlr.c b/hal/audio_extn/adsp_hdlr.c
index 31a6b16..f8c8133 100644
--- a/hal/audio_extn/adsp_hdlr.c
+++ b/hal/audio_extn/adsp_hdlr.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -457,7 +457,7 @@
 
 int audio_extn_adsp_hdlr_stream_register_event(void *handle, void *data,
                                                adsp_event_callback_t cb,
-                                               void *cookie)
+                                               void *cookie, bool is_adm_event)
 {
     int ret = 0;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
@@ -480,14 +480,22 @@
         ALOGE("%s: Invalid payload_length %d",__func__, param->payload_length);
         return -EINVAL;
     }
-    ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
+
+    if (is_adm_event)
+        ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
+            "ADSP COPP Callback Event");
+    else
+        ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
             "ADSP Stream Callback Event %d", config->pcm_device_id);
+
     if (ret < 0) {
         ALOGE("%s: snprintf failed",__func__);
         ret = -EINVAL;
         goto done;
     }
+
     ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, cb_mixer_ctl_name);
+
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
               cb_mixer_ctl_name);
@@ -495,8 +503,13 @@
         goto done;
     }
 
-    ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+    if (is_adm_event)
+        ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+            "COPP Event Cmd");
+    else
+       ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "ADSP Stream Cmd %d", config->pcm_device_id);
+
     if (ret < 0) {
         ALOGE("%s: snprintf failed",__func__);
         ret = -EINVAL;
@@ -504,12 +517,14 @@
     }
 
     ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, mixer_ctl_name);
+
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
               mixer_ctl_name);
         ret = -EINVAL;
         goto done;
     }
+
     ALOGD("%s: event = %d, payload_length %d", __func__, param->event_type, param->payload_length);
 
     /* copy event_type, payload size and payload */
@@ -521,6 +536,7 @@
            param->payload, param->payload_length);
     ret = mixer_ctl_set_array(ctl, payload, (sizeof(param->event_type) +
                                sizeof(param->payload_length) + param->payload_length));
+
     if (ret < 0) {
         ALOGE("%s: Could not set ctl for mixer cmd - %s, ret %d", __func__,
               mixer_ctl_name, ret);
@@ -537,23 +553,27 @@
 
         /* create event threads during first event registration */
         pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
+
         if (!adsp_hdlr_inst->event_wait_thread_active)
             create_event_wait_thread(adsp_hdlr_inst);
-        pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
 
+        pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
         pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
+
         if (!adsp_hdlr_inst->event_callback_thread_active)
             create_event_callback_thread(adsp_hdlr_inst);
-        pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
 
+        pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
         send_cmd_event_wait_thread(adsp_hdlr_inst, EVENT_CMD_WAIT);
     }
+
     event_info = (struct adsp_hdlr_event_info *) calloc(1,
                                    sizeof(struct adsp_hdlr_event_info));
     if (event_info == NULL) {
         ret = -ENOMEM;
         goto done;
     }
+
     event_info->event_type = param->event_type;
     event_info->cb = cb;
     event_info->cookie = cookie;
@@ -582,7 +602,7 @@
 
     switch (cmd) {
         case ADSP_HDLR_STREAM_CMD_REGISTER_EVENT :
-            ret = audio_extn_adsp_hdlr_stream_register_event(handle, param, NULL, NULL);
+            ret = audio_extn_adsp_hdlr_stream_register_event(handle, param, NULL, NULL, false);
             if (ret)
                 ALOGE("%s:adsp_hdlr_stream_register_event failed error %d",
                        __func__, ret);
diff --git a/hal/audio_extn/adsp_hdlr.h b/hal/audio_extn/adsp_hdlr.h
index 1c257fc..4ba9cb3 100644
--- a/hal/audio_extn/adsp_hdlr.h
+++ b/hal/audio_extn/adsp_hdlr.h
@@ -57,7 +57,7 @@
                     adsp_hdlr_cmd_t cmd,
                     void *param);
 int audio_extn_adsp_hdlr_stream_register_event(void *handle,
-                void *param, adsp_event_callback_t cb, void *cookie);
+                void *param, adsp_event_callback_t cb, void *cookie, bool is_adm_event);
 int audio_extn_adsp_hdlr_stream_deregister_event(void *handle, void *param);
 #else
 #define audio_extn_adsp_hdlr_init(mixer)                                     (0)
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index a0b1949..3fd4b85 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2017-2019, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -217,6 +217,7 @@
 typedef enum {
     AUDIO_STREAM_PP_EVENT = 0,
     AUDIO_STREAM_ENCDEC_EVENT = 1,
+    AUDIO_COPP_EVENT = 3,
 } audio_event_id;
 
 /* payload format for HAL parameter
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 5366066..76c8873 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -553,7 +553,8 @@
         inout->adsp_hdlr_stream_handle = NULL;
         goto exit;
     }
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format,false, true)) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format,false, true) ||
+        audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform)) {
         ret = audio_extn_ip_hdlr_intf_init(&inout->ip_hdlr_handle, NULL, NULL, adev,
                                            USECASE_AUDIO_TRANSCODE_LOOPBACK_RX);
         if (ret < 0) {
diff --git a/hal/audio_extn/ip_hdlr_intf.c b/hal/audio_extn/ip_hdlr_intf.c
old mode 100755
new mode 100644
index 3d5e1fe..0afc705
--- a/hal/audio_extn/ip_hdlr_intf.c
+++ b/hal/audio_extn/ip_hdlr_intf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -56,12 +56,19 @@
 #include "audio_extn.h"
 #include "platform_api.h"
 #include "adsp_hdlr.h"
+#include "audio_hw.h"
 
 /* These values defined by ADSP */
 #define ADSP_DEC_SERVICE_ID 1
 #define ADSP_EVENT_ID_RTIC            0x00013239
 #define ADSP_EVENT_ID_RTIC_FAIL       0x0001323A
+#define TRUMPET_TOPOLOGY 0x11000099
+#define TRUMPET_MODULE 0x0001099A
 
+struct lib_fd_info {
+    int32_t fd;
+    int32_t flag;
+};
 struct ip_hdlr_stream {
     struct listnode list;
     void *stream;
@@ -74,35 +81,109 @@
     int (*deinit)(void *handle);
     int (*open)(void *handle, bool is_dsp_decode, void *aud_sess_handle);
     int (*shm_info)(void *handle, int *fd);
+    int (*shm_pp_info)(void *handle, int *fd);
+    int (*shm_pp)(void *handle, bool is_adm_event);
     int (*get_lib_fd)(void *handle, int *lib_fd);
     int (*close)(void *handle);
     int (*event)(void *handle, void *payload);
     int (*reg_cb)(void *handle, void *ack_cb, void *fail_cb);
+    int (*event_adm)(void *handle, void *payload);
+    int (*deinit_lib)(void *handle);
+
 
     struct listnode stream_list;
     pthread_mutex_t stream_list_lock;
     int ref_cnt;
+    bool lib_fd_created;
+    void *ip_lib_handle; /*handle for dlclose of adsp lib*/
+    bool adm_event;
+    bool asm_event;
+    void *ip_dev_handle;
 };
 static struct ip_hdlr_intf *ip_hdlr = NULL;
-
+static bool adm_event_enable;
+static bool asm_event_enable;
+struct copp_cal_info {
+    uint32_t             persist;
+    uint32_t             snd_dev_id;
+    audio_devices_t      dev_id;
+    int32_t              acdb_dev_id;
+    uint32_t             app_type;
+    uint32_t             topo_id;
+    uint32_t             sampling_rate;
+    uint32_t             cal_type;
+    uint32_t             module_id;
+#ifdef INSTANCE_ID_ENABLED
+    uint16_t             instance_id;
+    uint16_t             reserved;
+#endif
+    uint32_t             param_id;
+};
+static struct copp_cal_info trumpet_data;
 /* RTIC ack information */
 struct rtic_ack_info {
     uint32_t token;
     uint32_t status;
 };
 
+struct module_info {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t token_coppidx;
+};
+
+struct rtic_ack_info_adm {
+    uint32_t token;
+    uint32_t status;
+    struct module_info mod_data;
+};
+
 /* RTIC ack format sent to ADSP */
 struct rtic_ack_param {
     uint32_t param_size;
     struct rtic_ack_info rtic_ack;
 };
 
+struct rtic_ack_param_adm {
+    uint32_t param_size;
+    struct rtic_ack_info rtic_ack;
+    struct module_info mod_data;
+};
+
 /* each event payload format */
 struct reg_ev_pl {
     uint32_t event_id;
     uint32_t cfg_mask;
 };
 
+struct reg_ev_pl_adm {
+    uint32_t event_id;
+    uint32_t module_id;
+    uint16_t instance_id;
+    uint16_t reserved;
+    uint32_t cfg_mask;
+};
+
+struct adm_pp_module {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t be_id;
+    uint32_t fe_id;
+};
+
+struct adm_fd_info {
+    uint32_t fd;
+    struct adm_pp_module adm_pp_pl_fd;
+};
+/* adm event registration format */
+struct adm_reg_event {
+    struct adm_pp_module adm_info;
+    uint16_t version;
+    uint32_t num_reg_events;
+    struct reg_ev_pl_adm rtic;
+    struct reg_ev_pl_adm rtic_fail;
+};
+
 /* event registration format */
 struct reg_event {
     uint16_t version;
@@ -121,23 +202,50 @@
     uint8_t payload[0];
 };
 
+int audio_extn_ip_hdlr_copp_update_cal_info(void *cfg, void *data)
+{
+    int ret = 0;
+    acdb_audio_cal_cfg_t *cal = (acdb_audio_cal_cfg_t*) cfg;
+    adm_event_enable = true; /* default enable with trumpet cal */
+
+    memcpy(&trumpet_data, cal, sizeof(struct copp_cal_info));
+    return ret;
+
+}
+bool audio_extn_ip_hdlr_intf_supported_for_copp(void *platform)
+{
+    return adm_event_enable;
+}
 bool audio_extn_ip_hdlr_intf_supported(audio_format_t format,
                     bool is_direct_passthrough,
                     bool is_transcode_loopback)
 {
 
-    if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_DOLBY_TRUEHD)
+    if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_DOLBY_TRUEHD) {
+        asm_event_enable = true;
         return true;
-    else if (!is_direct_passthrough && !audio_extn_qaf_is_enabled() &&
+    } else if (!is_direct_passthrough && !audio_extn_qaf_is_enabled() &&
             (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3) ||
-             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3)))
+             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3))) {
+        asm_event_enable = true;
         return true;
-    else if (is_transcode_loopback &&
+    } else if (is_transcode_loopback &&
             (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3) ||
-             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3)))
+             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3))) {
+        asm_event_enable = true;
         return true;
-    else
+    } else {
+        asm_event_enable = false;
         return false;
+    }
+}
+
+int audio_extn_ip_hdlr_intf_event_adm(void *stream_handle __unused,
+                               void *payload, void *ip_hdlr_handle )
+{
+    ALOGVV("%s:[%d] handle = %p\n",__func__, ip_hdlr->ref_cnt, ip_hdlr_handle);
+
+    return ip_hdlr->event_adm(ip_hdlr_handle, payload);
 }
 
 int audio_extn_ip_hdlr_intf_event(void *stream_handle __unused, void *payload, void *ip_hdlr_handle )
@@ -147,7 +255,82 @@
     return ip_hdlr->event(ip_hdlr_handle, payload);
 }
 
-int audio_extn_ip_hdlr_intf_rtic_ack(void *aud_sess_handle, struct rtic_ack_info *info)
+int audio_extn_ip_hdlr_intf_rtic_ack_adm(void *aud_sess_handle,
+                               struct rtic_ack_info_adm *info)
+{
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    int ret = 0;
+    int pcm_device_id = 0;
+    struct mixer_ctl *ctl = NULL;
+    struct rtic_ack_param_adm param;
+    struct listnode *node = NULL, *tempnode = NULL;
+    struct ip_hdlr_stream *stream_info = NULL;
+    struct audio_device *adev = NULL;
+    audio_usecase_t usecase = 0;
+
+    memset(&param, 0, sizeof(struct rtic_ack_param_adm));
+    pthread_mutex_lock(&ip_hdlr->stream_list_lock);
+    list_for_each_safe(node, tempnode, &ip_hdlr->stream_list) {
+        stream_info = node_to_item(node, struct ip_hdlr_stream, list);
+        /* send the error if rtic failure notifcation is received */
+        if ((stream_info->stream == aud_sess_handle) &&
+            (stream_info->usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)) {
+            struct stream_inout *inout = (struct stream_inout *)aud_sess_handle;
+            usecase = stream_info->usecase;
+            adev = inout->dev;
+            break;
+        } else if (stream_info->stream == aud_sess_handle) {
+            struct stream_out *out = (struct stream_out *)aud_sess_handle;
+            usecase = stream_info->usecase;
+            adev = out->dev;
+            break;
+        }
+    }
+    pthread_mutex_unlock(&ip_hdlr->stream_list_lock);
+
+    if (adev == NULL) {
+        ALOGE("%s:[%d] Invalid adev", __func__, ip_hdlr->ref_cnt);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    pcm_device_id = platform_get_pcm_device_id(usecase, PCM_PLAYBACK);
+
+    ALOGVV("%s:[%d] token = %d, info->status = %d, pcm_id = %d\n",__func__,
+          ip_hdlr->ref_cnt, info->token, info->status, pcm_device_id);
+
+    /* set mixer control to send RTIC done information */
+    ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                   "COPP Event Ack");
+    if (ret < 0) {
+        ALOGE("%s:[%d] snprintf failed",__func__, ip_hdlr->ref_cnt);
+        ret = -EINVAL;
+        goto done;
+    }
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s:[%d] Could not get ctl for mixer cmd - %s", __func__,
+              ip_hdlr->ref_cnt, mixer_ctl_name);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    param.param_size = sizeof(struct rtic_ack_info);
+    memcpy(&param.rtic_ack, info, sizeof(struct rtic_ack_info));
+    memcpy(&param.mod_data, &info->mod_data, sizeof(struct module_info));
+    ret = mixer_ctl_set_array(ctl, (void *)&param, sizeof(param));
+    if (ret < 0) {
+        ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d",
+                    __func__, ip_hdlr->ref_cnt, mixer_ctl_name, ret);
+        goto done;
+    }
+
+done:
+    return ret;
+}
+
+int audio_extn_ip_hdlr_intf_rtic_ack(void *aud_sess_handle,
+                                struct rtic_ack_info *info)
 {
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
     int ret = 0;
@@ -257,6 +440,139 @@
     return 0;
 }
 
+static int audio_extn_ip_hdlr_intf_open_adm_event(void *handle,
+                    void *stream_handle, audio_usecase_t usecase)
+{
+    int ret = 0, fd = 0, pcm_device_id = 0;
+    struct adm_fd_info *fd_param_data = NULL;
+    struct audio_adsp_event *param = NULL;
+    struct adm_reg_event *reg_ev = NULL;
+    size_t shm_size = 0;
+    void  *shm_buf = NULL;
+    struct stream_out *out = NULL;
+    struct stream_inout *inout = NULL;
+    void *adsp_hdlr_stream_handle = NULL;
+    struct audio_device *dev = NULL;
+    struct mixer_ctl *ctl = NULL;
+    struct audio_usecase *uc = NULL;
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+
+    param = (struct audio_adsp_event *)calloc(1,
+                sizeof(struct audio_adsp_event));
+
+    if (param == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    reg_ev = (struct adm_reg_event *)calloc(1, sizeof(struct adm_reg_event));
+
+    if (reg_ev == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    fd_param_data = (struct adm_fd_info *)calloc(1, sizeof(struct adm_fd_info));
+
+    if (fd_param_data == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    uc = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+    if (uc == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    if (usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX) {
+        inout = (struct stream_inout *)stream_handle;
+        adsp_hdlr_stream_handle = inout->adsp_hdlr_stream_handle;
+        dev = inout->dev;
+    } else {
+        out = (struct stream_out *)stream_handle;
+        adsp_hdlr_stream_handle = out->adsp_hdlr_stream_handle;
+        dev = out->dev;
+    }
+    uc = get_usecase_from_list(dev, usecase);
+
+    reg_ev->adm_info.module_id = TRUMPET_MODULE;
+    reg_ev->adm_info.instance_id = 0;
+    reg_ev->adm_info.be_id = platform_get_snd_device_backend_index(
+                                                uc->out_snd_device);
+    reg_ev->adm_info.fe_id = platform_get_pcm_device_id(usecase, PCM_PLAYBACK);
+    reg_ev->num_reg_events = 2;
+    reg_ev->rtic.event_id = ADSP_EVENT_ID_RTIC;
+    reg_ev->rtic.module_id = TRUMPET_MODULE;
+    reg_ev->rtic.instance_id = 0;
+    reg_ev->rtic.cfg_mask = 1; /* event enabled */
+    reg_ev->rtic_fail.event_id = ADSP_EVENT_ID_RTIC_FAIL;
+    reg_ev->rtic_fail.module_id = TRUMPET_MODULE;
+    reg_ev->rtic_fail.instance_id = 0;
+    reg_ev->rtic_fail.cfg_mask = 1; /* event enabled */
+
+    param->event_type = AUDIO_COPP_EVENT;
+    param->payload_length = sizeof(struct adm_reg_event);
+    param->payload = reg_ev;
+    bool is_adm_event = true;
+
+    /* Register for event and its callback */
+    ret = audio_extn_adsp_hdlr_stream_register_event(adsp_hdlr_stream_handle,
+               param, audio_extn_ip_hdlr_intf_event_adm, handle, is_adm_event);
+    if (ret < 0) {
+        ALOGE("%s:[%d] failed to register event",__func__,
+                                    ip_hdlr->ref_cnt, ret);
+        goto done;
+    }
+
+    ip_hdlr->reg_cb(handle, &audio_extn_ip_hdlr_intf_rtic_ack_adm,
+                                &audio_extn_ip_hdlr_intf_rtic_fail);
+    ip_hdlr->shm_pp_info(handle, &fd);
+    fd_param_data->fd = fd;
+    memcpy(&fd_param_data->adm_pp_pl_fd, &reg_ev->adm_info,
+                                sizeof(struct adm_pp_module));
+
+    ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "COPP ION FD");
+
+    if (ret < 0) {
+        ALOGE("%s:[%d] snprintf failed",__func__, ip_hdlr->ref_cnt, ret);
+        goto done;
+    }
+    ALOGV("%s: fd = %d\n", __func__, fd);
+
+    ctl = mixer_get_ctl_by_name(dev->mixer, mixer_ctl_name);
+
+    if (!ctl) {
+        ALOGE("%s:[%d] Could not get ctl for mixer cmd - %s", __func__,
+              ip_hdlr->ref_cnt, mixer_ctl_name);
+        ret = -EINVAL;
+        goto done;
+    }
+    ret = mixer_ctl_set_array(ctl, fd_param_data, sizeof(fd_param_data));
+
+    if (ret < 0) {
+        ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d"
+                , __func__, ip_hdlr->ref_cnt, mixer_ctl_name, ret);
+        goto done;
+    }
+
+done:
+    if (param)
+        free(param);
+
+    if (reg_ev)
+        free(reg_ev);
+
+    if (fd_param_data)
+        free(fd_param_data);
+
+    if (uc)
+        free(uc);
+
+    return ret;
+}
+
 static int audio_extn_ip_hdlr_intf_open_dsp(void *handle, void *stream_handle, audio_usecase_t usecase)
 {
     int ret = 0, fd = 0, pcm_device_id = 0;
@@ -268,7 +584,7 @@
     struct audio_device *dev = NULL;
     struct mixer_ctl *ctl = NULL;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
-
+    bool is_adm_event = false;
     param = (struct audio_adsp_event *)calloc(1, sizeof(struct audio_adsp_event));
     if (!param)
         return -ENOMEM;
@@ -301,7 +617,7 @@
     /* Register for event and its callback */
     ret = audio_extn_adsp_hdlr_stream_register_event(adsp_hdlr_stream_handle, param,
                                                      audio_extn_ip_hdlr_intf_event,
-                                                     handle);
+                                                     handle, is_adm_event);
     if (ret < 0) {
         ALOGE("%s:[%d] failed to register event %d",__func__, ip_hdlr->ref_cnt, ret);
         goto done;
@@ -363,12 +679,18 @@
     }
     ALOGD("%s:[%d] handle = %p, sess_handle = %p, is_dsp_decode = %d, usecase = %d",
           __func__, ip_hdlr->ref_cnt, handle, aud_sess_handle, is_dsp_decode, usecase);
-    if (is_dsp_decode) {
+    if (is_dsp_decode && ip_hdlr->asm_event) {
         ret = audio_extn_ip_hdlr_intf_open_dsp(handle, aud_sess_handle, usecase);
         if (ret < 0)
             ip_hdlr->close(handle);
     }
 
+    if (is_dsp_decode && ip_hdlr->adm_event) {
+        ret = audio_extn_ip_hdlr_intf_open_adm_event(handle, aud_sess_handle, usecase);
+        if (ret < 0)
+            ip_hdlr->close(handle);
+    }
+
     pthread_mutex_lock(&ip_hdlr->stream_list_lock);
     list_add_tail(&ip_hdlr->stream_list, &stream_info->list);
     pthread_mutex_unlock(&ip_hdlr->stream_list_lock);
@@ -430,10 +752,12 @@
                                  struct audio_device *dev, audio_usecase_t usecase)
 {
     int ret = 0, pcm_device_id;
-    int lib_fd;
+    struct lib_fd_info lib_fd;
     struct mixer_ctl *ctl = NULL;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
 
+    memset(&lib_fd, 0, sizeof(struct lib_fd_info));
+
     if (!ip_hdlr) {
         ip_hdlr = (struct ip_hdlr_intf *)calloc(1, sizeof(struct ip_hdlr_intf));
         if (!ip_hdlr)
@@ -451,44 +775,72 @@
         ip_hdlr->init =(int (*)(void **handle, char *lib_path,
                                 void **lib_handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_init");
         ip_hdlr->deinit = (int (*)(void *handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_deinit");
+        ip_hdlr->deinit_lib = (int (*)(void *handle))dlsym(ip_hdlr->lib_hdl,
+                                                "audio_ip_hdlr_deinit_lib");
         ip_hdlr->open = (int (*)(void *handle, bool is_dsp_decode,
                                  void *sess_handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_open");
         ip_hdlr->close =(int (*)(void *handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_close");
         ip_hdlr->reg_cb =(int (*)(void *handle, void *ack_cb,
                                   void *fail_cb))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_reg_cb");
-        ip_hdlr->shm_info =(int (*)(void *handle, int *fd))dlsym(ip_hdlr->lib_hdl,
-                                                                 "audio_ip_hdlr_shm_info");
+        ip_hdlr->shm_info =(int (*)(void *handle, int *fd))dlsym(
+                                   ip_hdlr->lib_hdl, "audio_ip_hdlr_shm_info");
+        ip_hdlr->shm_pp_info =(int (*)(void *handle, int *fd))dlsym(ip_hdlr->lib_hdl,
+                                                                 "audio_ip_hdlr_shm_pp_info");
         ip_hdlr->get_lib_fd =(int (*)(void *handle, int *fd))dlsym(ip_hdlr->lib_hdl,
                                                                  "audio_ip_hdlr_lib_fd");
         ip_hdlr->event =(int (*)(void *handle, void *payload))dlsym(ip_hdlr->lib_hdl,
                                                                     "audio_ip_hdlr_event");
+        ip_hdlr->event_adm =(int (*)(void *handle, void *payload))dlsym(
+                            ip_hdlr->lib_hdl, "audio_ip_hdlr_event_adm");
+        ip_hdlr->shm_pp = (int (*)(void *handle, bool is_adm_event))dlsym(
+                            ip_hdlr->lib_hdl, "audio_ip_hdlr_create_shm_pp");
         if (!ip_hdlr->init || !ip_hdlr->deinit || !ip_hdlr->open ||
             !ip_hdlr->close || !ip_hdlr->reg_cb || !ip_hdlr->shm_info ||
-            !ip_hdlr->event || !ip_hdlr->get_lib_fd) {
+            !ip_hdlr->event || !ip_hdlr->get_lib_fd || !ip_hdlr->deinit_lib ||
+            !ip_hdlr->shm_pp || !ip_hdlr->shm_pp_info || !ip_hdlr->event_adm) {
             ALOGE("%s: failed to get symbols", __func__);
             ret = -EINVAL;
             goto dlclose;
-
         }
     }
 
+    ip_hdlr->ip_dev_handle = dev;
     ret = ip_hdlr->init(handle, lib_path, lib_handle);
     if (ret < 0) {
         ALOGE("%s:[%d] init failed ret = %d", __func__, ip_hdlr->ref_cnt, ret);
         ret = -EINVAL;
         goto dlclose;
     }
-    if (!lib_path) {
-        ip_hdlr->get_lib_fd(*handle, &lib_fd);
 
-        pcm_device_id = platform_get_pcm_device_id(usecase, PCM_PLAYBACK);
+    if (adm_event_enable) {
+        ret = ip_hdlr->shm_pp(*handle, adm_event_enable);
+
+        if (ret < 0) {
+            ALOGE("%s:[%d] init failed ret = %d", __func__, ip_hdlr->ref_cnt, ret);
+            ret = -EINVAL;
+            goto dlclose;
+        }
+        ip_hdlr->adm_event = adm_event_enable;
+        adm_event_enable = false;
+    }
+
+    if (asm_event_enable) {
+        ip_hdlr->asm_event = asm_event_enable;
+        asm_event_enable = false;
+    }
+
+    if (!lib_path && !(ip_hdlr->lib_fd_created)) {
+        /* save handle to dlcose of lib fd */
+        ip_hdlr->ip_lib_handle = handle;
+        ip_hdlr->get_lib_fd(*handle, &lib_fd.fd);
+        lib_fd.flag = 1;
+        /* sending lib ion fd to routing driver */
         ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
-                       "Playback ION LIB FD %d", pcm_device_id);
+                       "ADSP ION LIB FD");
         if (ret < 0) {
             ALOGE("%s:[%d] snprintf failed %d", __func__, ip_hdlr->ref_cnt, ret);
             goto dlclose;
         }
-        ALOGV("%s: fd = %d  pcm_id = %d", __func__, lib_fd, pcm_device_id);
 
         ctl = mixer_get_ctl_by_name(dev->mixer, mixer_ctl_name);
         if (!ctl) {
@@ -497,12 +849,14 @@
             ret = -EINVAL;
             goto dlclose;
         }
-        ret = mixer_ctl_set_array(ctl, &lib_fd, sizeof(lib_fd));
+
+        ret = mixer_ctl_set_array(ctl, &lib_fd, sizeof(struct lib_fd_info));
         if (ret < 0) {
             ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d", __func__, ip_hdlr->ref_cnt,
                   mixer_ctl_name, ret);
             goto dlclose;
         }
+        ip_hdlr->lib_fd_created = true;
     }
     ip_hdlr->ref_cnt++;
     ALOGD("%s:[%d] init done", __func__, ip_hdlr->ref_cnt);
@@ -521,6 +875,12 @@
 int audio_extn_ip_hdlr_intf_deinit(void *handle)
 {
     int ret = 0;
+    struct lib_fd_info lib_fd;
+    struct mixer_ctl *ctl = NULL;
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    struct audio_device *ip_dev = (struct audio_device *) (ip_hdlr->ip_dev_handle);
+
+    memset(&lib_fd, 0, sizeof(struct lib_fd_info));
 
     if (!handle) {
         ALOGE("%s:[%d] handle is NULL", __func__, ip_hdlr->ref_cnt);
@@ -532,12 +892,41 @@
         ALOGE("%s:[%d] deinit failed ret = %d", __func__, ip_hdlr->ref_cnt, ret);
 
     if (--ip_hdlr->ref_cnt == 0) {
+        ip_hdlr->get_lib_fd(handle, &lib_fd.fd);
+        lib_fd.flag = 0;
+        /* sending lib ion fd to routing driver */
+        ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                       "ADSP ION LIB FD");
+        if (ret < 0) {
+            ALOGE("%s:[%d] snprintf failed %d"
+                , __func__, ip_hdlr->ref_cnt, ret);
+            goto dlclose;
+        }
+
+        ctl = mixer_get_ctl_by_name(ip_dev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s:[%d] Could not get ctl for mixer cmd - %s", __func__,
+                  ip_hdlr->ref_cnt, mixer_ctl_name);
+            ret = -EINVAL;
+            goto dlclose;
+        }
+        ret = mixer_ctl_set_array(ctl, &lib_fd, sizeof(struct lib_fd_info));
+        if (ret < 0) {
+            ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d"
+                        , __func__, ip_hdlr->ref_cnt, mixer_ctl_name, ret);
+            goto dlclose;
+        }
+
+        ret = ip_hdlr->deinit_lib(ip_hdlr->ip_lib_handle);
+        ip_hdlr->lib_fd_created = false;
         if (ip_hdlr->lib_hdl)
             dlclose(ip_hdlr->lib_hdl);
-
+dlclose:
         pthread_mutex_destroy(&ip_hdlr->stream_list_lock);
         free(ip_hdlr);
         ip_hdlr = NULL;
     }
+    ALOGD("%s: done\n", __func__);
     return ret;
+
 }
diff --git a/hal/audio_extn/ip_hdlr_intf.h b/hal/audio_extn/ip_hdlr_intf.h
index 6040620..5cfbc24 100644
--- a/hal/audio_extn/ip_hdlr_intf.h
+++ b/hal/audio_extn/ip_hdlr_intf.h
@@ -41,6 +41,8 @@
 bool audio_extn_ip_hdlr_intf_supported(audio_format_t format,
                                        bool is_direct_passthru,
                                        bool is_transcode_loopback);
+bool audio_extn_ip_hdlr_intf_supported_for_copp(void *platform);
+int audio_extn_ip_hdlr_copp_update_cal_info(void *cfg, void *data);
 
 #else
 
@@ -49,6 +51,8 @@
 #define audio_extn_ip_hdlr_intf_init(handle, lib_path, lib_handlei, adev, usecase)     (0)
 #define audio_extn_ip_hdlr_intf_deinit(handle)                                (0)
 #define audio_extn_ip_hdlr_intf_supported(format, is_direct_passthru, is_loopback) (0)
+#define audio_extn_ip_hdlr_intf_supported_for_copp(platform) (0)
+#define audio_extn_ip_hdlr_copp_update_cal_info(cfg, data) (0)
 
 #endif
 
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7a9022e..c98d82c 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -960,7 +960,7 @@
 }
 
 static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
-{ 
+{
     struct audio_effect_config effect_config;
     struct audio_usecase *usecase = NULL;
     int ret = 0;
@@ -6612,7 +6612,7 @@
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
-    int ret = 0;
+    int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
     audio_format_t format;
     struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
     bool is_direct_passthough = false;
@@ -7361,7 +7361,8 @@
     is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
     if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
             (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
-            (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
+        audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
+        (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
         hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
                 out->usecase, PCM_PLAYBACK);
         hdlr_stream_cfg.flags = out->flags;
@@ -7373,7 +7374,10 @@
             out->adsp_hdlr_stream_handle = NULL;
         }
     }
-    if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
+    ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
+                                            is_direct_passthough, false);
+    ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
+    if (ip_hdlr_stream || ip_hdlr_dev ) {
         ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index a428f9a..aa9d16e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1658,9 +1658,9 @@
 
     if (enable) {
         if (!voice_extn_is_compress_voip_supported()) {
-        if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
-            strlcat(ec_ref_mixer_path, "-voip", MIXER_PATH_MAX_LENGTH);
-        }        
+            if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
+                strlcat(ec_ref_mixer_path, "-voip", MIXER_PATH_MAX_LENGTH);
+        }
         strlcpy(my_data->ec_ref_mixer_path, ec_ref_mixer_path,
                     MIXER_PATH_MAX_LENGTH);
         /*
@@ -9571,6 +9571,9 @@
         ret = -EINVAL;
         goto ERROR_RETURN;
     }
+    if ((cal->acdb_dev_id == ACDB_ID_STEREO_SPEAKER_DEVICE) &&
+       (cal->topo_id == TRUMPET_TOPOLOGY))
+        audio_extn_ip_hdlr_copp_update_cal_info((void*)cal, data);
 
     if (my_data->acdb_set_audio_cal) {
         // persist audio cal in local cache
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 2cb1741..ba7b01a 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -21,6 +21,9 @@
 #define QCOM_AUDIO_PLATFORM_H
 #include <sound/voice_params.h>
 
+#define TRUMPET_TOPOLOGY 0x11000099
+#define ACDB_ID_STEREO_SPEAKER_DEVICE 15
+
 enum {
     FLUENCE_NONE,
     FLUENCE_DUAL_MIC = 0x1,