Merge 9c4ba54b3ecb1ee854763970b3057220994dad8a on remote branch

Change-Id: I5a80c57243eda5a4fdd98a233766cd622b4ef9a3
diff --git a/Android.mk b/Android.mk
index 6e129a1..6d8a9f9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
-ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916 msm8994 msm8992 msm8909 msm8996 msm8952,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916 msm8994 msm8992 msm8909 msm8996 msm8952 msm8937 thorium,$(TARGET_BOARD_PLATFORM)),)
 
 MY_LOCAL_PATH := $(call my-dir)
 
diff --git a/audiod/Android.mk b/audiod/Android.mk
index 2092620..c89b3cd 100644
--- a/audiod/Android.mk
+++ b/audiod/Android.mk
@@ -2,6 +2,10 @@
 
 include $(CLEAR_VARS)
 
+ifneq (,$(findstring $(PLATFORM_VERSION), 5.0 5.1 5.1.1))
+include external/stlport/libstlport.mk
+endif
+
 LOCAL_SRC_FILES:= \
 	audiod_main.cpp \
 	AudioDaemon.cpp \
@@ -14,6 +18,10 @@
 	libbinder \
 	libmedia
 
+ifneq (,$(findstring $(PLATFORM_VERSION), 5.0 5.1 5.1.1))
+LOCAL_SHARED_LIBRARIES += libstlport
+endif
+
 LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 
 LOCAL_MODULE:= audiod
diff --git a/hal/Android.mk b/hal/Android.mk
index 4e6bf91..4bd87f9 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -32,7 +32,7 @@
 endif
 endif
 
-ifneq ($(filter msm8916 msm8909 msm8952,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8916 msm8909 msm8952 msm8937 thorium,$(TARGET_BOARD_PLATFORM)),)
   AUDIO_PLATFORM = msm8916
   MULTIPLE_HW_VARIANTS_ENABLED := true
   LOCAL_CFLAGS := -DPLATFORM_MSM8916
@@ -53,8 +53,8 @@
 LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_EDID)),true)
-    LOCAL_SRC_FILES += edid.c
     LOCAL_CFLAGS += -DHDMI_EDID
+    LOCAL_SRC_FILES += edid.c
 endif
 
 ifeq ($(strip $(AUDIO_USE_LL_AS_PRIMARY_OUTPUT)),true)
@@ -161,10 +161,6 @@
 endif
 endif
 
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MULTIPLE_TUNNEL)), true)
-    LOCAL_CFLAGS += -DMULTIPLE_OFFLOAD_ENABLED
-endif
-
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true)
     LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED
     LOCAL_CFLAGS += -DCOMPRESS_METADATA_NEEDED
@@ -258,9 +254,11 @@
 
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_HDMI)),true)
     LOCAL_CFLAGS += -DAUDIO_EXTERNAL_HDMI_ENABLED
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH)),true)
     LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-parsers
     LOCAL_SHARED_LIBRARIES += libaudioparsers
 endif
+endif
 
 ifeq ($(strip $(BOARD_SUPPORTS_SOUND_TRIGGER)),true)
     LOCAL_CFLAGS += -DSOUND_TRIGGER_ENABLED
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 7154ab0..fe959be 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -874,9 +874,7 @@
 static perf_lock_acquire_t perf_lock_acq;
 static perf_lock_release_t perf_lock_rel;
 
-static int perf_lock_handle;
 char opt_lib_path[512] = {0};
-int perf_lock_opts[1] = {0x20E};
 
 int audio_extn_perf_lock_init(void)
 {
@@ -914,19 +912,30 @@
     return ret;
 }
 
-void audio_extn_perf_lock_acquire(void)
+void audio_extn_perf_lock_acquire(int *handle, int duration,
+                                 int *perf_lock_opts, int size)
 {
-    if (perf_lock_acq)
-        perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 1);
-    else
-        ALOGE("%s: Perf lock acquire error \n", __func__);
+
+    if (!perf_lock_opts || !size || !perf_lock_acq || !handle)
+        return -EINVAL;
+    /*
+     * Acquire performance lock for 1 sec during device path bringup.
+     * Lock will be released either after 1 sec or when perf_lock_release
+     * function is executed.
+     */
+    *handle = perf_lock_acq(*handle, duration, perf_lock_opts, size);
+    if (*handle <= 0)
+        ALOGE("%s: Failed to acquire perf lock, err: %d\n",
+              __func__, *handle);
 }
 
-void audio_extn_perf_lock_release(void)
+void audio_extn_perf_lock_release(int *handle)
 {
-    if (perf_lock_rel && perf_lock_handle)
-        perf_lock_rel(perf_lock_handle);
-    else
+    if (perf_lock_rel && handle && (*handle > 0)) {
+        perf_lock_rel(*handle);
+        *handle = 0;
+    } else {
         ALOGE("%s: Perf lock release error \n", __func__);
+    }
 }
 #endif /* KPI_OPTIMIZE_ENABLED */
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index d87d407..5231e93 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -48,7 +48,7 @@
 #define audio_is_offload_pcm(format) (0)
 #define OFFLOAD_USE_SMALL_BUFFER false
 #else
-#define OFFLOAD_USE_SMALL_BUFFER ((info->format & AUDIO_FORMAT_PCM_OFFLOAD) == AUDIO_FORMAT_PCM_OFFLOAD)
+#define OFFLOAD_USE_SMALL_BUFFER ((info->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)
 #endif
 
 #ifndef AFE_PROXY_ENABLED
@@ -275,6 +275,7 @@
 #define audio_extn_spkr_prot_is_enabled() (false)
 #define audio_extn_spkr_prot_get_acdb_id(snd_device)         (-EINVAL)
 #define audio_extn_get_spkr_prot_snd_device(snd_device) (snd_device)
+#define audio_extn_spkr_prot_set_parameters(parms, value, len)   (0)
 #else
 void audio_extn_spkr_prot_init(void *adev);
 int audio_extn_spkr_prot_start_processing(snd_device_t snd_device);
@@ -283,6 +284,8 @@
 int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device);
 int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device);
 void audio_extn_spkr_prot_calib_cancel(void *adev);
+void audio_extn_spkr_prot_set_parameters(struct str_parms *parms,
+                                         char *value, int len);
 #endif
 
 #ifndef COMPRESS_CAPTURE_ENABLED
@@ -308,6 +311,7 @@
 #define audio_extn_dts_eagle_set_parameters(adev, parms)     (0)
 #define audio_extn_dts_eagle_get_parameters(adev, query, reply) (0)
 #define audio_extn_dts_eagle_fade(adev, fade_in, out) (0)
+#define audio_extn_dts_eagle_send_lic()               (0)
 #define audio_extn_dts_create_state_notifier_node(stream_out) (0)
 #define audio_extn_dts_notify_playback_state(stream_out, has_video, sample_rate, \
                                     channels, is_playing) (0)
@@ -319,6 +323,7 @@
 int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
                   struct str_parms *query, struct str_parms *reply);
 int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in, const struct stream_out *out);
+void audio_extn_dts_eagle_send_lic();
 void audio_extn_dts_create_state_notifier_node(int stream_out);
 void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
                                   int channels, int is_playing);
@@ -443,7 +448,8 @@
                                   uint32_t bit_width,
                                   audio_channel_mask_t channel_mask,
                                   struct stream_app_type_cfg *app_type_cfg);
-int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase);
+int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
+                                       struct audio_usecase *usecase);
 void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
                                              struct audio_usecase *usecase);
 #ifdef DS2_DOLBY_DAP_ENABLED
@@ -495,17 +501,19 @@
 
 #ifndef KPI_OPTIMIZE_ENABLED
 #define audio_extn_perf_lock_init() (0)
-#define audio_extn_perf_lock_acquire() (0)
-#define audio_extn_perf_lock_release() (0)
+#define audio_extn_perf_lock_acquire(handle, duration, opts, size) (0)
+#define audio_extn_perf_lock_release(handle) (0)
 #else
 int audio_extn_perf_lock_init(void);
-void audio_extn_perf_lock_acquire(void);
-void audio_extn_perf_lock_release(void);
+void audio_extn_perf_lock_acquire(int *handle, int duration,
+                                 int *opts, int size);
+void audio_extn_perf_lock_release(int *handle);
+
 #endif /* KPI_OPTIMIZE_ENABLED */
 
 #ifndef AUDIO_EXTERNAL_HDMI_ENABLED
-#define setChannelStatus(out, buffer, bytes) (0)
+#define audio_utils_set_hdmi_channel_status(out, buffer, bytes) (0)
 #else
-void setChannelStatus(struct stream_out *out, char * buffer, size_t bytes);
+void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes);
 #endif
 #endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
index 7608a61..71bfea6 100644
--- a/hal/audio_extn/dts_eagle.c
+++ b/hal/audio_extn/dts_eagle.c
@@ -39,6 +39,7 @@
 #define STATE_NOTIFY_FILE               "/data/misc/dts/stream"
 #define FADE_NOTIFY_FILE                "/data/misc/dts/fade"
 #define DTS_EAGLE_KEY                   "DTS_EAGLE"
+#define DEVICE_NODE                     "/dev/snd/hwC0D3"
 #define MAX_LENGTH_OF_INTEGER_IN_STRING 13
 #define PARAM_GET_MAX_SIZE              512
 
@@ -116,7 +117,7 @@
     }
 
     if (!sent) {
-        int fd = open(GENERIC_AUDIO_DEVICE_NODE, O_RDWR);
+        int fd = open(DEVICE_NODE, O_RDWR);
 
         if (get) {
             ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to retrieve directly from cache", __func__);
@@ -136,7 +137,7 @@
             }
             close(fd);
         } else {
-            ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, GENERIC_AUDIO_DEVICE_NODE);
+            ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, DEVICE_NODE);
             ret = -EINVAL;
         }
     }
@@ -189,6 +190,28 @@
     return 0;
 }
 
+void audio_extn_dts_eagle_send_lic() {
+    char prop[PROPERTY_VALUE_MAX] = {0};
+    bool enabled;
+    property_get("use.dts_eagle", prop, "0");
+    enabled = !strncmp("true", prop, sizeof("true")) || atoi(prop);
+    if (!enabled)
+        return;
+    int fd = open(DEVICE_NODE, O_RDWR);
+    int index = 1;
+    if (fd >= 0) {
+        if (ioctl(fd, DTS_EAGLE_IOCTL_SEND_LICENSE, &index) < 0) {
+            ALOGE("DTS_EAGLE_HAL: error sending license after adsp ssr");
+        } else {
+            ALOGD("DTS_EAGLE_HAL: sent license after adsp ssr");
+        }
+        close(fd);
+    } else {
+        ALOGE("DTS_EAGLE_HAL: error opening eagle");
+    }
+    return;
+}
+
 void audio_extn_dts_eagle_set_parameters(struct audio_device *adev, struct str_parms *parms) {
     int ret, val;
     char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index fcf5eb0..6381e68 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index a73dfa1..3e09e55 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -47,6 +47,8 @@
 
 #ifdef PLATFORM_MSM8994
 #define HFP_RX_VOLUME     "SEC AUXPCM LOOPBACK Volume"
+#elif defined PLATFORM_MSM8996
+#define HFP_RX_VOLUME     "PRI AUXPCM LOOPBACK Volume"
 #else
 #define HFP_RX_VOLUME     "Internal HFP RX Volume"
 #endif
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index c13c2f3..3c16c88 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -334,18 +334,6 @@
         event.u.value = val;
         st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
     }
-
-    ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
-    if ((ret >= 0) && audio_is_input_device(val)) {
-        event.u.value = val;
-        st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
-    }
-
-    ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
-    if ((ret >= 0) && audio_is_input_device(val)) {
-        event.u.value = val;
-        st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
-    }
 }
 
 int audio_extn_sound_trigger_init(struct audio_device *adev)
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 040b140..efa885e 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -95,15 +95,20 @@
 #define SPKR_PROCESSING_IN_PROGRESS 1
 #define SPKR_PROCESSING_IN_IDLE 0
 
-#ifdef PLATFORM_MSM8916
-#define ACDB_DEVICE_SPKR_PROT_WSA_ANALOG 136
-#define ACDB_DEVICE_VI_FEEDBACK_WSA_ANALOG 137
-#endif
-
 #define MAX_PATH             (256)
 #define THERMAL_SYSFS "/sys/class/thermal"
 #define TZ_TYPE "/sys/class/thermal/thermal_zone%d/type"
 #define TZ_WSA "/sys/class/thermal/thermal_zone%d/temp"
+
+#define AUDIO_PARAMETER_KEY_SPKR_TZ_1     "spkr_1_tz_name"
+#define AUDIO_PARAMETER_KEY_SPKR_TZ_2     "spkr_2_tz_name"
+
+#define SPKR_TZ_1    "wsatz.12"
+#define SPKR_TZ_2    "wsatz.11"
+#define SPKR_TZ_3    "wsatz.14"
+#define SPKR_TZ_4    "wsatz.13"
+
+
 /*Modes of Speaker Protection*/
 enum speaker_protection_mode {
     SPKR_PROTECTION_DISABLED = -1,
@@ -137,8 +142,6 @@
     bool spkr_in_use;
     struct timespec spkr_last_time_used;
     bool wsa_found;
-    char *spkr_1_tz_name;
-    char *spkr_2_tz_name;
     int spkr_1_tzn;
     int spkr_2_tzn;
 };
@@ -154,8 +157,14 @@
     .avail_min = 0,
 };
 
+struct spkr_tz_names {
+    char *spkr_1_name;
+    char *spkr_2_name;
+};
+
 static struct speaker_prot_session handle;
 static int vi_feed_no_channels;
+static struct spkr_tz_names tz_names;
 
 /*===========================================================================
 FUNCTION get_tzn
@@ -753,7 +762,7 @@
                 continue;
            }
            if (goahead) {
-               if (spk_1_tzn > 0) {
+               if (spk_1_tzn >= 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_1_tzn);
                    ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
                    thermal_fd = -1;
@@ -796,7 +805,7 @@
                        continue;
                    }
                }
-               if (spk_2_tzn > 0) {
+               if (spk_2_tzn >= 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
                    ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
                    thermal_fd = open(wsa_path, O_RDONLY);
@@ -923,15 +932,42 @@
 
 static bool is_wsa_present(void)
 {
-   handle.spkr_1_tz_name = platform_get_spkr_1_tz_name(SND_DEVICE_OUT_SPEAKER);
-   handle.spkr_2_tz_name = platform_get_spkr_2_tz_name(SND_DEVICE_OUT_SPEAKER);
-   handle.spkr_1_tzn = get_tzn(handle.spkr_1_tz_name);
-   handle.spkr_2_tzn = get_tzn(handle.spkr_2_tz_name);
+   ALOGD("%s: tz1: %s, tz2: %s", __func__,
+          tz_names.spkr_1_name, tz_names.spkr_2_name);
+   handle.spkr_1_tzn = get_tzn(tz_names.spkr_1_name);
+   handle.spkr_2_tzn = get_tzn(tz_names.spkr_2_name);
    if ((handle.spkr_1_tzn >= 0) || (handle.spkr_2_tzn >= 0))
         handle.wsa_found = true;
    return handle.wsa_found;
 }
 
+void audio_extn_spkr_prot_set_parameters(struct str_parms *parms,
+                                         char *value, int len)
+{
+    int err;
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SPKR_TZ_1,
+                            value, len);
+    if (err >= 0) {
+        if ((!strncmp(SPKR_TZ_1, value, sizeof(SPKR_TZ_1)) ||
+            (!strncmp(SPKR_TZ_3, value, sizeof(SPKR_TZ_3)))))
+            tz_names.spkr_1_name = strdup(value);
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SPKR_TZ_1);
+    }
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SPKR_TZ_2,
+                            value, len);
+    if (err >= 0) {
+        if ((!strncmp(SPKR_TZ_2, value, sizeof(SPKR_TZ_2)) ||
+            (!strncmp(SPKR_TZ_4, value, sizeof(SPKR_TZ_4)))))
+            tz_names.spkr_2_name = strdup(value);
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_SPKR_TZ_2);
+    }
+
+    ALOGV("%s: tz1: %s, tz2: %s", __func__,
+          tz_names.spkr_1_name, tz_names.spkr_2_name);
+}
+
 void audio_extn_spkr_prot_init(void *adev)
 {
     char value[PROPERTY_VALUE_MAX];
@@ -955,24 +991,6 @@
     handle.spkr_prot_t0 = -1;
 
     if (is_wsa_present()) {
-#ifdef PLATFORM_MSM8916
-        if (platform_get_wsa_mode(adev) == 1) {
-            ALOGD("%s: WSA analog mode", __func__);
-            platform_set_snd_device_backend(SND_DEVICE_OUT_VOICE_SPEAKER_WSA,
-                                            "speaker-protected");
-            platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED,
-                                            ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
-            platform_set_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
-                                            ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
-            platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT,
-                                            ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
-            platform_set_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT,
-                                            ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
-	    platform_set_snd_device_acdb_id(SND_DEVICE_IN_CAPTURE_VI_FEEDBACK,
-                                            ACDB_DEVICE_VI_FEEDBACK_WSA_ANALOG);
-            pcm_config_skr_prot.channels = 2;
-        }
-#endif
         pthread_cond_init(&handle.spkr_calib_cancel, NULL);
         pthread_cond_init(&handle.spkr_calibcancel_ack, NULL);
         pthread_mutex_init(&handle.mutex_spkr_prot, NULL);
@@ -981,6 +999,8 @@
         (void)pthread_create(&handle.spkr_calibration_thread,
         (const pthread_attr_t *) NULL, spkr_calibration_thread, &handle);
         return;
+    } else {
+        ALOGD("%s: WSA spkr calibration thread is not created", __func__);
     }
     pthread_cond_init(&handle.spkr_prot_thermalsync, NULL);
     pthread_cond_init(&handle.spkr_calib_cancel, NULL);
@@ -1047,9 +1067,7 @@
 
     switch(snd_device) {
     case SND_DEVICE_OUT_SPEAKER:
-#ifdef PLATFORM_MSM8916
     case SND_DEVICE_OUT_SPEAKER_WSA:
-#endif
         acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED);
         break;
     case SND_DEVICE_OUT_SPEAKER_VBAT:
@@ -1059,9 +1077,9 @@
         acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT);
         break;
     case SND_DEVICE_OUT_VOICE_SPEAKER:
-#ifdef PLATFORM_MSM8916
+
     case SND_DEVICE_OUT_VOICE_SPEAKER_WSA:
-#endif
+
         acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED);
         break;
     default:
@@ -1078,18 +1096,14 @@
 
     switch(snd_device) {
     case SND_DEVICE_OUT_SPEAKER:
-#ifdef PLATFORM_MSM8916
     case SND_DEVICE_OUT_SPEAKER_WSA:
-#endif
         return SND_DEVICE_OUT_SPEAKER_PROTECTED;
     case SND_DEVICE_OUT_SPEAKER_VBAT:
         return SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT;
     case SND_DEVICE_OUT_VOICE_SPEAKER_VBAT:
         return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT;
     case SND_DEVICE_OUT_VOICE_SPEAKER:
-#ifdef PLATFORM_MSM8916
     case SND_DEVICE_OUT_VOICE_SPEAKER_WSA:
-#endif
         return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED;
     default:
         return snd_device;
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index e917367..9ec4243 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -36,8 +36,10 @@
 #include "voice.h"
 
 #ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#ifdef HDMI_PASSTHROUGH_ENABLED
 #include "audio_parsers.h"
 #endif
+#endif
 
 #define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
 
@@ -57,18 +59,18 @@
 #define MAX_BASEINDEX_LEN 256
 
 #ifdef AUDIO_EXTERNAL_HDMI_ENABLED
-#define PROFESSIONAL        (1<<0)	/* 0 = consumer, 1 = professional */
-#define NON_LPCM	    (1<<1)	/* 0 = audio, 1 = non-audio */
-#define SR_44100	    (0<<0)	/* 44.1kHz */
-#define SR_NOTID	    (1<<0)	/* non indicated */
-#define SR_48000	    (2<<0)	/* 48kHz */
-#define SR_32000	    (3<<0)	/* 32kHz */
-#define SR_22050	    (4<<0)	/* 22.05kHz */
-#define SR_24000	    (6<<0)	/* 24kHz */
-#define SR_88200	    (8<<0)	/* 88.2kHz */
-#define SR_96000	    (10<<0)	/* 96kHz */
-#define SR_176400	    (12<<0)	/* 176.4kHz */
-#define SR_192000	    (14<<0)	/* 192kHz */
+#define PROFESSIONAL        (1<<0)      /* 0 = consumer, 1 = professional */
+#define NON_LPCM            (1<<1)      /* 0 = audio, 1 = non-audio */
+#define SR_44100            (0<<0)      /* 44.1kHz */
+#define SR_NOTID            (1<<0)      /* non indicated */
+#define SR_48000            (2<<0)      /* 48kHz */
+#define SR_32000            (3<<0)      /* 32kHz */
+#define SR_22050            (4<<0)      /* 22.05kHz */
+#define SR_24000            (6<<0)      /* 24kHz */
+#define SR_88200            (8<<0)      /* 88.2kHz */
+#define SR_96000            (10<<0)     /* 96kHz */
+#define SR_176400           (12<<0)     /* 176.4kHz */
+#define SR_192000           (14<<0)     /* 192kHz */
 
 #endif
 struct string_to_enum {
@@ -88,7 +90,9 @@
 #ifdef INCALL_MUSIC_ENABLED
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
 #endif
+#ifdef HDMI_PASSTHROUGH_ENABLED
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
+#endif
 };
 
 const struct string_to_enum s_format_name_to_enum_table[] = {
@@ -103,7 +107,6 @@
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
 #ifdef AUDIO_EXTN_FORMATS_ENABLED
     STRING_TO_ENUM(AUDIO_FORMAT_DTS),
-    STRING_TO_ENUM(AUDIO_FORMAT_DTS_LBR),
     STRING_TO_ENUM(AUDIO_FORMAT_WMA),
     STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
@@ -540,12 +543,11 @@
     app_type_cfg->bit_width = 16;
 }
 
-int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase)
+int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
+                                       struct audio_usecase *usecase)
 {
     char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
     int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
-    struct stream_out *out;
-    struct audio_device *adev;
     struct mixer_ctl *ctl;
     int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
     int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
@@ -553,25 +555,27 @@
 
     ALOGV("%s", __func__);
 
-    if (usecase->type != PCM_PLAYBACK) {
-        ALOGV("%s: not a playback path, no need to cfg app type", __func__);
+    if (usecase->type != PCM_PLAYBACK && usecase->type != PCM_CAPTURE) {
+        ALOGE("%s: not a playback or capture path, no need to cfg app type", __func__);
         rc = 0;
         goto exit_send_app_type_cfg;
     }
     if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
-        (!is_offload_usecase(usecase->id))) {
-        ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id);
+        (!is_offload_usecase(usecase->id)) &&
+        (usecase->type != PCM_CAPTURE)) {
+        ALOGV("%s: a rx/tx path where app type cfg is not required %d", __func__, usecase->id);
         rc = 0;
         goto exit_send_app_type_cfg;
     }
-    out = usecase->stream.out;
-    adev = out->dev;
-
-    snd_device = usecase->out_snd_device;
-
-    pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+    if (usecase->type == PCM_PLAYBACK) {
+        snd_device = usecase->out_snd_device;
+        pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
+    } else if (usecase->type == PCM_CAPTURE) {
+        snd_device = usecase->in_snd_device;
+        pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
+    }
 
     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
              "Audio Stream %d App Type Cfg", pcm_device_id);
@@ -591,37 +595,33 @@
         rc = -EINVAL;
         goto exit_send_app_type_cfg;
     }
-
     if ((24 == usecase->stream.out->bit_width) &&
         (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
-        out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+        usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
     } else if ((snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
         usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
         (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
-        out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+        usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
     }
-    sample_rate = out->app_type_cfg.sample_rate;
+    sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
 
     property_get("audio.playback.mch.downsample",value,"");
     if (!strncmp("true", value, sizeof("true"))) {
-        if ((popcount(out->channel_mask) > 2) &&
-               (out->sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
-               !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
+        if ((popcount(usecase->stream.out->channel_mask) > 2) &&
+               (usecase->stream.out->app_type_cfg.sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
+               !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
            sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     }
 
-    app_type_cfg[len++] = out->app_type_cfg.app_type;
+    app_type_cfg[len++] = usecase->stream.out->app_type_cfg.app_type;
     app_type_cfg[len++] = acdb_dev_id;
-    if (((out->format == AUDIO_FORMAT_E_AC3) ||
-        (out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
-        (out->flags  & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
+    if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
+        (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
+        (usecase->stream.out->flags  & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
         app_type_cfg[len++] = sample_rate * 4;
     else
         app_type_cfg[len++] = sample_rate;
-
     mixer_ctl_set_array(ctl, app_type_cfg, len);
-    ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
-           __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
     rc = 0;
 exit_send_app_type_cfg:
     return rc;
@@ -660,13 +660,13 @@
                      audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
         platform_send_audio_calibration(adev->platform, usecase,
                                         out->app_type_cfg.app_type,
-                                        out->app_type_cfg.sample_rate);
+                                        usecase->stream.out->app_type_cfg.sample_rate);
     }
     if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
         /* when app type is default. the sample rate is not used to send cal */
         platform_send_audio_calibration(adev->platform, usecase,
-                                        platform_get_default_app_type(adev->platform),
-                                        48000);
+                 platform_get_default_app_type_v2(adev->platform, usecase->type),
+                 48000);
     }
 }
 
@@ -830,6 +830,7 @@
      channel_status[3] |= SR_48000;
 }
 
+#ifdef HDMI_PASSTHROUGH_ENABLED
 int32_t get_compressed_channel_status(void *audio_stream_data,
                                                    uint32_t audio_frame_size,
                                                    unsigned char *channel_status,
@@ -837,9 +838,9 @@
                                                    // codec_type - AUDIO_PARSER_CODEC_AC3
                                                    //            - AUDIO_PARSER_CODEC_DTS
 {
-     unsigned char *streamPtr;
+     unsigned char *stream;
      int ret = 0;
-     streamPtr = (unsigned char *)audio_stream_data;
+     stream = (unsigned char *)audio_stream_data;
 
      if (audio_stream_data == NULL || audio_frame_size == 0) {
          ALOGW("no buffer to get channel status, return default for compress");
@@ -848,7 +849,7 @@
      }
 
      memset(channel_status,0,24);
-     if(init_audio_parser(streamPtr, audio_frame_size, codec_type) == -1)
+     if(init_audio_parser(stream, audio_frame_size, codec_type) == -1)
      {
          ALOGE("init audio parser failed");
          return -1;
@@ -858,7 +859,9 @@
 
 }
 
-void get_linearpcm_channel_status(uint32_t sampleRate,
+#endif
+
+void get_lpcm_channel_status(uint32_t sampleRate,
                                                   unsigned char *channel_status)
 {
      int32_t status = 0;
@@ -876,6 +879,7 @@
          case 16000:
          case 22050:
              channel_status[3] |= SR_NOTID;
+             break;
          case 24000:
              channel_status[3] |= SR_24000;
              break;
@@ -907,21 +911,24 @@
      }
 }
 
-void setChannelStatus(struct stream_out *out, char * buffer, size_t bytes)
+void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes)
 {
     unsigned char channel_status[24]={0};
     struct snd_aes_iec958 iec958;
     const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
     struct mixer_ctl *ctl;
     int i=0;
+#ifdef HDMI_PASSTHROUGH_ENABLED
     if (audio_extn_is_dolby_format(out->format) &&
         /*TODO:Extend code to support DTS passthrough*/
         /*set compressed channel status bits*/
         audio_extn_dolby_is_passthrough_stream(out->flags)){
         get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
-    } else {
+    } else
+#endif
+    {
         /*set channel status bit for LPCM*/
-        get_linearpcm_channel_status(out->sample_rate, channel_status);
+        get_lpcm_channel_status(out->sample_rate, channel_status);
     }
 
     memcpy(iec958.status, channel_status,sizeof(iec958.status));
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
old mode 100755
new mode 100644
index 711b1f4..a0f9206
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -165,9 +165,10 @@
 const char * const use_case_table[AUDIO_USECASE_MAX] = {
     [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
-    [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
+    [USECASE_AUDIO_PLAYBACK_ULL]         = "audio-ull-playback",
+    [USECASE_AUDIO_PLAYBACK_MULTI_CH]    = "multi-channel-playback",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
-#ifdef MULTIPLE_OFFLOAD_ENABLED
+    //Enabled for Direct_PCM
     [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
@@ -176,9 +177,6 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
-#endif
-    [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
-    [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
 
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
@@ -214,7 +212,6 @@
 
 static const audio_usecase_t offload_usecases[] = {
     USECASE_AUDIO_PLAYBACK_OFFLOAD,
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     USECASE_AUDIO_PLAYBACK_OFFLOAD2,
     USECASE_AUDIO_PLAYBACK_OFFLOAD3,
     USECASE_AUDIO_PLAYBACK_OFFLOAD4,
@@ -223,8 +220,6 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD7,
     USECASE_AUDIO_PLAYBACK_OFFLOAD8,
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
-#endif
-    USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
 };
 
 #define STRING_TO_ENUM(string) { #string, string }
@@ -256,6 +251,26 @@
 
 static int set_voice_volume_l(struct audio_device *adev, float volume);
 
+__attribute__ ((visibility ("default")))
+bool audio_hw_send_gain_dep_calibration(int level) {
+    bool ret_val = false;
+    ALOGV("%s: called ... ", __func__);
+
+    pthread_mutex_lock(&adev_init_lock);
+
+    if (adev != NULL && adev->platform != NULL) {
+        pthread_mutex_lock(&adev->lock);
+        ret_val = platform_send_gain_dep_cal(adev->platform, level);
+        pthread_mutex_unlock(&adev->lock);
+    } else {
+        ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
+    }
+
+    pthread_mutex_unlock(&adev_init_lock);
+
+    return ret_val;
+}
+
 static int check_and_set_gapless_mode(struct audio_device *adev) {
 
 
@@ -369,7 +384,10 @@
         return -ENOSYS;
 
     pthread_mutex_lock(&adev->snd_card_status.lock);
-    adev->snd_card_status.state = snd_scard_state;
+    if (adev->snd_card_status.state != snd_scard_state) {
+        adev->snd_card_status.state = snd_scard_state;
+        platform_snd_card_update(adev->platform, snd_scard_state);
+    }
     pthread_mutex_unlock(&adev->snd_card_status.lock);
 
     return 0;
@@ -430,7 +448,7 @@
     audio_extn_dolby_ds2_set_endpoint(adev);
     audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
     audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
-    audio_extn_utils_send_app_type_cfg(usecase);
+    audio_extn_utils_send_app_type_cfg(adev, usecase);
     audio_extn_utils_send_audio_calibration(adev, usecase);
     strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
     platform_add_backend_name(mixer_path, snd_device, usecase);
@@ -498,7 +516,7 @@
     if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
        audio_extn_usb_start_capture(adev);
 
-    if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
+	   if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
         snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
         snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
         audio_extn_spkr_prot_is_enabled()) {
@@ -566,7 +584,6 @@
         /* exit usb capture thread */
         if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
             audio_extn_usb_stop_capture();
-
         if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
             snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
             snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
@@ -577,10 +594,7 @@
         }
 
         if (snd_device == SND_DEVICE_OUT_HDMI)
-            adev->mChannelStatusSet = false;
-
-        if (snd_device == SND_DEVICE_OUT_HDMI)
-            adev->mChannelStatusSet = false;
+            adev->is_channel_status_set = false;
 
         audio_extn_dev_arbi_release(snd_device);
         audio_extn_sound_trigger_update_device_status(snd_device,
@@ -676,10 +690,9 @@
            specified usecase to new snd devices */
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
-            /* Update the out_snd_device only before enabling the audio route */
-            if (switch_device[usecase->id] ) {
-                usecase->out_snd_device = snd_device;
-                if (usecase->type != VOICE_CALL)
+            /* Update the out_snd_device only for the usecases that are enabled here */
+            if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
+                    usecase->out_snd_device = snd_device;
                     enable_audio_route(adev, usecase);
             }
         }
@@ -714,8 +727,7 @@
                 usecase != uc_info &&
                 usecase->in_snd_device != snd_device &&
                 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
-                 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
-                  (usecase->type == VOICE_CALL))) &&
+                ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
                 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
             ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
                   __func__, use_case_table[usecase->id],
@@ -915,8 +927,6 @@
 
     if (out_snd_device == usecase->out_snd_device &&
         in_snd_device == usecase->in_snd_device) {
-        audio_extn_dolby_set_endpoint(adev);
-        audio_extn_dolby_ds2_set_endpoint(adev);
         return 0;
     }
 
@@ -1112,7 +1122,9 @@
     uc_info->out_snd_device = SND_DEVICE_NONE;
 
     list_add_tail(&adev->usecase_list, &uc_info->list);
-    audio_extn_perf_lock_acquire();
+    audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
+                                 adev->perf_lock_opts,
+                                 adev->perf_lock_opts_size);
     select_devices(adev, in->usecase);
 
     ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
@@ -1154,16 +1166,14 @@
         goto error_open;
     }
 
-    audio_extn_perf_lock_release();
-
+    audio_extn_perf_lock_release(&adev->perf_lock_handle);
     ALOGD("%s: exit", __func__);
 
     return ret;
 
 error_open:
+    audio_extn_perf_lock_release(&adev->perf_lock_handle);
     stop_input_stream(in);
-    audio_extn_perf_lock_release();
-
 error_config:
     adev->active_input = NULL;
     /*
@@ -1232,35 +1242,50 @@
     return false;
 }
 
-static audio_usecase_t get_offload_usecase(struct audio_device *adev)
+static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
 {
-    audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
-    unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
-    char value[PROPERTY_VALUE_MAX] = {0};
+    audio_usecase_t ret_uc = USECASE_INVALID;
+    unsigned int offload_uc_index;
+    int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
+    if (!adev->multi_offload_enable) {
+        if (is_direct_pcm)
+            ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
+        else
+            ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
 
-    property_get("audio.offload.multiple.enabled", value, NULL);
-    if (!(atoi(value) || !strncmp("true", value, 4)))
-        num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
+        pthread_mutex_lock(&adev->lock);
+        if (get_usecase_from_list(adev, ret_uc) != NULL)
+           ret_uc = USECASE_INVALID;
+        pthread_mutex_unlock(&adev->lock);
+
+        return ret_uc;
+    }
 
     ALOGV("%s: num_usecase: %d", __func__, num_usecase);
-    for (i = 0; i < num_usecase; i++) {
-        if (!(adev->offload_usecases_state & (0x1<<i))) {
-            adev->offload_usecases_state |= 0x1 << i;
-            ret = offload_usecases[i];
+    for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
+        if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
+            adev->offload_usecases_state |= 0x1 << offload_uc_index;
+            ret_uc = offload_usecases[offload_uc_index];
             break;
         }
     }
-    ALOGV("%s: offload usecase is %d", __func__, ret);
-    return ret;
+
+    ALOGV("%s: offload usecase is %d", __func__, ret_uc);
+    return ret_uc;
 }
 
 static void free_offload_usecase(struct audio_device *adev,
                                  audio_usecase_t uc_id)
 {
-    unsigned int i;
-    for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
-        if (offload_usecases[i] == uc_id) {
-            adev->offload_usecases_state &= ~(0x1<<i);
+    unsigned int offload_uc_index;
+    int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
+
+    if (!adev->multi_offload_enable)
+        return;
+
+    for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
+        if (offload_usecases[offload_uc_index] == uc_id) {
+            adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
             break;
         }
     }
@@ -1617,6 +1642,9 @@
     }
     list_add_tail(&adev->usecase_list, &uc_info->list);
 
+    audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
+                                 adev->perf_lock_opts,
+                                 adev->perf_lock_opts_size);
     select_devices(adev, out->usecase);
 
     ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
@@ -1707,11 +1735,12 @@
             audio_extn_check_and_set_dts_hpx_state(adev);
         }
     }
-
+    audio_extn_perf_lock_release(&adev->perf_lock_handle);
     ALOGD("%s: exit", __func__);
 
     return 0;
 error_open:
+    audio_extn_perf_lock_release(&adev->perf_lock_handle);
     stop_output_stream(out);
 error_config:
     /*
@@ -1975,8 +2004,13 @@
         if (val != 0) {
             out->devices = val;
 
-            if (!out->standby)
+            if (!out->standby) {
+                audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
+                                             adev->perf_lock_opts,
+                                             adev->perf_lock_opts_size);
                 select_devices(adev, out->usecase);
+                audio_extn_perf_lock_release(&adev->perf_lock_handle);
+            }
 
             if (output_drives_call(adev, out)) {
                 if(!voice_is_in_call(adev)) {
@@ -2063,6 +2097,21 @@
         }
     }
 
+
+    ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
+    if (ret >= 0) {
+        value[0] = '\0';
+        if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
+            ALOGV("in direct_pcm");
+            strlcat(value, "true", strlen("true"));
+        } else {
+            ALOGV("not in direct_pcm");
+            strlcat(value, "false", strlen("false"));
+        }
+        str_parms_add_str(reply, "is_direct_pcm_track", value);
+        str = str_parms_to_str(reply);
+    }
+
     ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
     if (ret >= 0) {
         value[0] = '\0';
@@ -2190,13 +2239,13 @@
             out->standby = true;
             goto exit;
         }
-        if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
+        if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
             adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
     }
 
-    if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
-        setChannelStatus(out, buffer, bytes);
-        adev->mChannelStatusSet = true;
+    if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
+        audio_utils_set_hdmi_channel_status(out, buffer, bytes);
+        adev->is_channel_status_set = true;
     }
 
     if (is_offload_usecase(out->usecase)) {
@@ -2275,7 +2324,7 @@
 
     if (ret != 0) {
         if (out->pcm)
-            ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
+            ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
         if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
             pthread_mutex_lock(&adev->lock);
             voice_extn_compress_voip_close_output_stream(&out->stream.common);
@@ -2882,6 +2931,7 @@
     out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     out->non_blocking = 0;
     out->use_small_bufs = false;
+
     /* Init use case and pcm_config */
     if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
         !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
@@ -2956,18 +3006,24 @@
         }
 
         if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
-            ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
-            out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
+            out->usecase = get_offload_usecase(adev, true);
+            ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
         } else {
-            ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
-            out->usecase = get_offload_usecase(adev);
-
             out->stream.set_callback = out_set_callback;
             out->stream.pause = out_pause;
             out->stream.resume = out_resume;
             out->stream.drain = out_drain;
             out->stream.flush = out_flush;
+            out->usecase = get_offload_usecase(adev, false);
+            ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
         }
+
+        if (out->usecase == USECASE_INVALID) {
+            ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
+            ret = -EEXIST;
+            goto error_open;
+        }
+
         if (config->offload_info.channel_mask)
             out->channel_mask = config->offload_info.channel_mask;
         else if (config->channel_mask) {
@@ -3269,12 +3325,8 @@
         } else if (strstr(snd_card_status, "ONLINE")) {
             ALOGD("Received sound card ONLINE status");
             set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
-            if (!platform_is_acdb_initialized(adev->platform)) {
-                ret = platform_acdb_init(adev->platform);
-                if(ret)
-                   ALOGE("acdb initialization is failed");
-
-            }
+            //send dts hpx license if enabled
+            audio_extn_dts_eagle_send_lic();
         }
     }
 
@@ -3632,7 +3684,6 @@
     /* This stream could be for sound trigger lab,
        get sound trigger pcm if present */
     audio_extn_sound_trigger_check_and_get_session(in);
-    audio_extn_perf_lock_init();
 
     *stream_in = &in->stream;
     ALOGV("%s: exit", __func__);
@@ -3792,7 +3843,10 @@
     list_init(&adev->usecase_list);
     adev->cur_wfd_channels = 2;
     adev->offload_usecases_state = 0;
-    adev->mChannelStatusSet = false;
+    adev->is_channel_status_set = false;
+    adev->perf_lock_opts[0] = 0x101;
+    adev->perf_lock_opts[1] = 0x20E;
+    adev->perf_lock_opts_size = 2;
 
     pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
     adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
@@ -3904,11 +3958,13 @@
         }
     }
 
+    adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
     pthread_mutex_unlock(&adev_init_lock);
 
     if (adev->adm_init)
         adev->adm_data = adev->adm_init();
 
+    audio_extn_perf_lock_init();
     ALOGV("%s: exit", __func__);
     return 0;
 }
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 85be217..fd19211 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -38,6 +38,7 @@
 #ifndef QCOM_AUDIO_HW_H
 #define QCOM_AUDIO_HW_H
 
+#include <stdlib.h>
 #include <cutils/list.h>
 #include <hardware/audio.h>
 #include <tinyalsa/asoundlib.h>
@@ -73,6 +74,8 @@
 #define SND_CARD_STATE_OFFLINE 0
 #define SND_CARD_STATE_ONLINE 1
 
+#define MAX_PERF_LOCK_OPTS 20
+
 /* These are the supported use cases by the hardware.
  * Each usecase is mapped to a specific PCM device.
  * Refer to pcm_device_table[].
@@ -84,7 +87,6 @@
     USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
     USECASE_AUDIO_PLAYBACK_MULTI_CH,
     USECASE_AUDIO_PLAYBACK_OFFLOAD,
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     USECASE_AUDIO_PLAYBACK_OFFLOAD2,
     USECASE_AUDIO_PLAYBACK_OFFLOAD3,
     USECASE_AUDIO_PLAYBACK_OFFLOAD4,
@@ -93,11 +95,8 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD7,
     USECASE_AUDIO_PLAYBACK_OFFLOAD8,
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
-#endif
     USECASE_AUDIO_PLAYBACK_ULL,
 
-    USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
-
     /* FM usecase */
     USECASE_AUDIO_PLAYBACK_FM,
 
@@ -328,7 +327,7 @@
     int snd_card;
     unsigned int cur_codec_backend_samplerate;
     unsigned int cur_codec_backend_bit_width;
-    bool mChannelStatusSet;
+    bool is_channel_status_set;
     void *platform;
     unsigned int offload_usecases_state;
     void *visualizer_lib;
@@ -340,9 +339,6 @@
 
     struct sound_card_status snd_card_status;
     int (*offload_effects_set_hpx_state)(bool);
-    void (*offload_effects_get_parameters)(struct str_parms *,
-                                           struct str_parms *);
-    void (*offload_effects_set_parameters)(struct str_parms *);
 
     void *adm_data;
     void *adm_lib;
@@ -353,6 +349,15 @@
     adm_deregister_stream_t adm_deregister_stream;
     adm_request_focus_t adm_request_focus;
     adm_abandon_focus_t adm_abandon_focus;
+
+    void (*offload_effects_get_parameters)(struct str_parms *,
+                                           struct str_parms *);
+    void (*offload_effects_set_parameters)(struct str_parms *);
+
+    bool multi_offload_enable;
+    int perf_lock_handle;
+    int perf_lock_opts[MAX_PERF_LOCK_OPTS];
+    int perf_lock_opts_size;
 };
 
 int select_devices(struct audio_device *adev,
diff --git a/hal/edid.h b/hal/edid.h
index aa945bd..0d7fbe6 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -92,7 +92,6 @@
     int  channel_allocation;
 } edid_audio_info;
 
-
 #ifndef HDMI_EDID
 #define edid_get_sink_caps(info, edid_data) (0)
 #else
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index 613c1a7..d04c69c 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -239,15 +239,15 @@
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
-     } else if (!strcmp(snd_card_name, "msm8976-tasha-snd-card")) {
+     } else if (!strcmp(snd_card_name, "msm8952-tasha-snd-card")) {
         strlcpy(hw_info->type, "", sizeof(hw_info->type));
-        strlcpy(hw_info->name, "msm8976", sizeof(hw_info->name));
+        strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
-    } else if (!strcmp(snd_card_name, "msm8976-tasha-skun-snd-card")) {
+    } else if (!strcmp(snd_card_name, "msm8952-tashalite-snd-card")) {
        strlcpy(hw_info->type, "", sizeof(hw_info->type));
-       strlcpy(hw_info->name, "msm8976", sizeof(hw_info->name));
+       strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
        hw_info->snd_devices = NULL;
        hw_info->num_snd_devices = 0;
        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
@@ -257,12 +257,30 @@
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
-    }  else if (!strcmp(snd_card_name, "msm8976-skun-snd-card")) {
+    } else if (!strcmp(snd_card_name, "msm8952-sku1-snd-card")) {
+        strlcpy(hw_info->type, "", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8952-sku2-snd-card")) {
+        strlcpy(hw_info->type, "", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+     } else if (!strcmp(snd_card_name, "msm8976-tasha-snd-card")) {
         strlcpy(hw_info->type, "", sizeof(hw_info->type));
         strlcpy(hw_info->name, "msm8976", sizeof(hw_info->name));
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8976-tashalite-snd-card")) {
+       strlcpy(hw_info->type, "", sizeof(hw_info->type));
+       strlcpy(hw_info->name, "msm8976", sizeof(hw_info->name));
+       hw_info->snd_devices = NULL;
+       hw_info->num_snd_devices = 0;
+       strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
     } else {
         ALOGW("%s: Not an  8x16/8939/8909/8952 device", __func__);
     }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index dfdb6d6..463dc77 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -52,6 +52,8 @@
 #define MIXER_XML_PATH_SKUE "/system/etc/mixer_paths_skue.xml"
 #define MIXER_XML_PATH_SKUL "/system/etc/mixer_paths_skul.xml"
 #define MIXER_XML_PATH_SKUM "/system/etc/mixer_paths_qrd_skum.xml"
+#define MIXER_XML_PATH_SKU1 "/system/etc/mixer_paths_qrd_sku1.xml"
+#define MIXER_XML_PATH_SKU2 "/system/etc/mixer_paths_qrd_sku2.xml"
 #define MIXER_XML_PATH_SKUN_CAJON "/system/etc/mixer_paths_qrd_skun_cajon.xml"
 #define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
 #define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
@@ -145,8 +147,6 @@
 
 #define  AUDIO_PARAMETER_IS_HW_DECODER_SESSION_AVAILABLE  "is_hw_dec_session_available"
 
-#define MAX_DSP_ONLY_DECODERS 6
-
 char * dsp_only_decoders_mime[] = {
     "audio/x-ms-wma" /* wma*/ ,
     "audio/x-ms-wma-lossless" /* wma lossless */ ,
@@ -191,6 +191,7 @@
 acdb_loader_get_calibration_t acdb_loader_get_calibration;
 typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
 typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
+typedef int (*acdb_send_common_top_t) (void);
 typedef int (*acdb_set_codec_data_t) (void *, char *);
 
 typedef struct codec_backend_cfg {
@@ -238,6 +239,7 @@
     acdb_send_voice_cal_t      acdb_send_voice_cal;
     acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
     acdb_get_default_app_type_t acdb_get_default_app_type;
+    acdb_send_common_top_t     acdb_send_common_top;
     acdb_set_codec_data_t      acdb_set_codec_data;
 #ifdef RECORD_PLAY_CONCURRENCY
     bool rec_play_conc_set;
@@ -252,11 +254,17 @@
 
 static bool is_external_codec = false;
 static const int pcm_device_table_of_ext_codec[AUDIO_USECASE_MAX][2] = {
-   [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC, QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC}
+   [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC, QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC},
+   [USECASE_VOICEMMODE1_CALL] = {VOICEMMODE1_CALL_PCM_DEVICE_OF_EXT_CODEC,
+                                 VOICEMMODE1_CALL_PCM_DEVICE_OF_EXT_CODEC},
+   [USECASE_VOICEMMODE2_CALL] = {VOICEMMODE2_CALL_PCM_DEVICE_OF_EXT_CODEC,
+                                 VOICEMMODE2_CALL_PCM_DEVICE_OF_EXT_CODEC},
 };
 
 /* List of use cases that has different PCM device ID's for internal and external codecs */
-static const int misc_usecase[AUDIO_USECASE_MAX] = { USECASE_QCHAT_CALL };
+static const int misc_usecase[AUDIO_USECASE_MAX] = {USECASE_QCHAT_CALL,
+                                                    USECASE_VOICEMMODE1_CALL,
+                                                    USECASE_VOICEMMODE2_CALL};
 
 int pcm_device_table[AUDIO_USECASE_MAX][2] = {
     [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
@@ -267,7 +275,6 @@
                                         MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     /* Below entries are initialized with invalid values
      * Valid values should be updated from fnc platform_info_init()
      * based on pcm ids defined in audio_platform_info.xml.
@@ -280,10 +287,7 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = {-1, -1},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = {-1, -1},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = {-1, -1},
-#endif
     [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE, MULTIMEDIA3_PCM_DEVICE},
-    [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] =
-                     {PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2},
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -298,8 +302,10 @@
     [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
     [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
     [USECASE_VOWLAN_CALL] = {VOWLAN_CALL_PCM_DEVICE, VOWLAN_CALL_PCM_DEVICE},
-    [USECASE_VOICEMMODE1_CALL] = {-1, -1}, /* pcm ids updated from platform info file */
-    [USECASE_VOICEMMODE2_CALL] = {-1, -1}, /* pcm ids updated from platform info file */
+    [USECASE_VOICEMMODE1_CALL] = {VOICEMMODE1_CALL_PCM_DEVICE,
+                                  VOICEMMODE1_CALL_PCM_DEVICE},
+    [USECASE_VOICEMMODE2_CALL] = {VOICEMMODE2_CALL_PCM_DEVICE,
+                                  VOICEMMODE2_CALL_PCM_DEVICE},
     [USECASE_COMPRESS_VOIP_CALL] = {COMPRESS_VOIP_CALL_PCM_DEVICE, COMPRESS_VOIP_CALL_PCM_DEVICE},
     [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
                                    AUDIO_RECORD_PCM_DEVICE},
@@ -666,7 +672,6 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD2)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD3)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD4)},
@@ -675,9 +680,7 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD7)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
-#endif
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
-    {TO_NAME_INDEX(USECASE_AUDIO_DIRECT_PCM_OFFLOAD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
@@ -774,11 +777,17 @@
      if (!strncmp(snd_card_name, "msm8939-tapan-snd-card",
                   sizeof("msm8939-tapan-snd-card")) ||
          !strncmp(snd_card_name, "msm8939-tapan9302-snd-card",
-                  sizeof("msm8939-tapan9302-snd-card"))||
+                  sizeof("msm8939-tapan9302-snd-card")) ||
          !strncmp(snd_card_name, "msm8939-tomtom9330-snd-card",
                   sizeof("msm8939-tomtom9330-snd-card")) ||
          !strncmp(snd_card_name, "msm8952-tomtom-snd-card",
                   sizeof("msm8952-tomtom-snd-card")) ||
+         !strncmp(snd_card_name, "msm8952-tasha-snd-card",
+                  sizeof("msm8952-tasha-snd-card")) ||
+         !strncmp(snd_card_name, "msm8952-tashalite-snd-card",
+                  sizeof("msm8952-tashalite-snd-card")) ||
+         !strncmp(snd_card_name, "msm8952-tasha-skun-snd-card",
+                  sizeof("msm8952-tasha-skun-snd-card")) ||
          !strncmp(snd_card_name, "msm8976-tasha-snd-card",
                   sizeof("msm8976-tasha-snd-card")) ||
          !strncmp(snd_card_name, "msm8976-tashalite-snd-card",
@@ -945,7 +954,7 @@
         msm_be_id_array_len  =
             sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
     } else if (!strncmp(snd_card_name, "msm8952-snd-card-mtp",
-                 sizeof("msm8952-snd-card-mtpmsm8952-snd-card-mtp"))) {
+                 sizeof("msm8952-snd-card-mtp"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_MTP,
                 sizeof(MIXER_XML_PATH_MTP));
         msm_device_to_be_id = msm_device_to_be_id_internal_codec;
@@ -958,6 +967,20 @@
         msm_device_to_be_id = msm_device_to_be_id_external_codec;
         msm_be_id_array_len  =
             sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_external_codec[0]);
+    }  else if (!strncmp(snd_card_name, "msm8952-sku1-snd-card",
+                 sizeof("msm8952-sku1-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_SKU1,
+                sizeof(MIXER_XML_PATH_SKU1));
+        msm_device_to_be_id = msm_device_to_be_id_internal_codec;
+        msm_be_id_array_len  =
+            sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
+    }  else if (!strncmp(snd_card_name, "msm8952-sku2-snd-card",
+                 sizeof("msm8952-sku2-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_SKU2,
+                sizeof(MIXER_XML_PATH_SKU2));
+        msm_device_to_be_id = msm_device_to_be_id_internal_codec;
+        msm_be_id_array_len  =
+            sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
     } else if (!strncmp(snd_card_name, "msm8952-skum-snd-card",
                  sizeof("msm8952-skum-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUM,
@@ -965,6 +988,21 @@
         msm_device_to_be_id = msm_device_to_be_id_internal_codec;
         msm_be_id_array_len  =
             sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
+    } else if (!strncmp(snd_card_name, "msm8952-tasha-snd-card",
+                 sizeof("msm8952-tasha-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_WCD9335,
+                sizeof(MIXER_XML_PATH_WCD9335));
+        msm_device_to_be_id = msm_device_to_be_id_external_codec;
+        msm_be_id_array_len  =
+            sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_external_codec[0]);
+
+    } else if (!strncmp(snd_card_name, "msm8952-tashalite-snd-card",
+                 sizeof("msm8952-tashalite-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_WCD9326,
+               MAX_MIXER_XML_PATH);
+        msm_device_to_be_id = msm_device_to_be_id_external_codec;
+        msm_be_id_array_len  =
+            sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_external_codec[0]);
     } else if (!strncmp(snd_card_name, "msm8976-skun-snd-card",
                  sizeof("msm8976-skun-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUN_CAJON,
@@ -1299,7 +1337,8 @@
     return ret;
 }
 
-static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, struct platform_data *plat_data, int fd)
+static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration,
+                          struct platform_data *plat_data, int fd)
 {
     int ret = 0, type;
 
@@ -1307,15 +1346,15 @@
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
 
+        /* MAD calibration is handled by sound trigger HAL, skip here */
+        if (type == WCD9XXX_MAD_CAL)
+            continue;
+
         if((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
            ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
            if (ret < 0)
                ALOGE("%s error in sending vbat adc data to acdb", __func__);
-	}
-
-        /* MAD calibration is handled by sound trigger HAL, skip here */
-        if (type == WCD9XXX_MAD_CAL)
-            continue;
+        }
 
         calib.get_size = 1;
         ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
@@ -1503,6 +1542,7 @@
     int wsaCount =0;
 
     my_data = calloc(1, sizeof(struct platform_data));
+
     if (!my_data) {
         ALOGE("failed to allocate platform data");
         return NULL;
@@ -1686,6 +1726,13 @@
             ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
                   __func__, LIB_ACDB_LOADER);
 
+        my_data->acdb_send_common_top = (acdb_send_common_top_t)dlsym(
+                                                    my_data->acdb_handle,
+                                                    "acdb_loader_send_common_custom_topology");
+        if (!my_data->acdb_send_common_top)
+            ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+                  __func__, LIB_ACDB_LOADER);
+
         my_data->acdb_set_codec_data = (acdb_set_codec_data_t)dlsym(
                                                     my_data->acdb_handle,
                                                     "acdb_loader_set_codec_data");
@@ -1717,9 +1764,9 @@
 
     /* Initialize ACDB and PCM ID's */
     if (is_external_codec)
-        platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC);
+        platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data);
     else
-        platform_info_init(PLATFORM_INFO_XML_PATH);
+        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
 
     /* init usb */
     audio_extn_usb_init(adev);
@@ -1776,8 +1823,6 @@
         (platform_get_native_support() ? "enabled" : "disabled"),
         snd_card_name);
 
-
-
     my_data->edid_info = NULL;
     return my_data;
 }
@@ -1816,13 +1861,27 @@
     audio_extn_dap_hal_deinit();
 }
 
-int platform_is_acdb_initialized(void *platform)
+static int platform_is_acdb_initialized(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     ALOGD("%s: acdb initialized %d\n", __func__, my_data->is_acdb_initialized);
     return my_data->is_acdb_initialized;
 }
 
+void platform_snd_card_update(void *platform, int snd_scard_state)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (snd_scard_state == SND_CARD_STATE_ONLINE) {
+        if (!platform_is_acdb_initialized(my_data)) {
+            if(platform_acdb_init(my_data))
+                ALOGE("%s: acdb initialization is failed", __func__);
+        } else if (my_data->acdb_send_common_top() < 0) {
+                ALOGD("%s: acdb did not set common topology", __func__);
+        }
+    }
+}
+
 const char *platform_get_snd_device_name(snd_device_t snd_device)
 {
     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
@@ -2015,6 +2074,14 @@
         return DEFAULT_APP_TYPE;
 }
 
+int platform_get_default_app_type_v2(void *platform, usecase_type_t  type)
+{
+    if(type == PCM_CAPTURE)
+        return DEFAULT_APP_TYPE_TX_PATH;
+    else
+        return DEFAULT_APP_TYPE_RX_PATH;
+}
+
 int platform_get_snd_device_acdb_id(snd_device_t snd_device)
 {
     if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
@@ -2168,6 +2235,9 @@
 
     if (usecase->type == PCM_PLAYBACK)
         snd_device = usecase->out_snd_device;
+    else if ((usecase->type == PCM_CAPTURE) &&
+                   voice_is_in_call_rec_stream(usecase->stream.in))
+        snd_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
         snd_device = usecase->in_snd_device;
     acdb_dev_id = acdb_device_table[audio_extn_get_spkr_prot_snd_device(snd_device)];
@@ -2224,8 +2294,9 @@
     if (my_data->csd == NULL)
         return ret;
 
-    if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
-        audio_extn_spkr_prot_is_enabled()) {
+    if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+         out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+         audio_extn_spkr_prot_is_enabled()) {
         if (my_data->is_vbat_speaker)
             acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
         else
@@ -2287,8 +2358,9 @@
     if (my_data->csd == NULL)
         return ret;
 
-    if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
-        audio_extn_spkr_prot_is_enabled()) {
+    if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+         out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+         audio_extn_spkr_prot_is_enabled()) {
         if (my_data->is_vbat_speaker)
             acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
          else
@@ -3634,7 +3706,7 @@
 int platform_update_usecase_from_source(int source, int usecase)
 {
     ALOGV("%s: input source :%d", __func__, source);
-    if(source == AUDIO_SOURCE_FM_TUNER)
+    if (source == AUDIO_SOURCE_FM_TUNER)
         usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
     return usecase;
 }
@@ -3661,7 +3733,6 @@
     case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
     case USECASE_AUDIO_PLAYBACK_MULTI_CH:
     case USECASE_AUDIO_PLAYBACK_OFFLOAD:
-    case USECASE_AUDIO_DIRECT_PCM_OFFLOAD:
         needs_event = true;
         break;
     /* concurrent playback in low latency allowed */
@@ -3725,7 +3796,6 @@
     case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
     case USECASE_AUDIO_PLAYBACK_MULTI_CH:
     case USECASE_AUDIO_PLAYBACK_OFFLOAD:
-    case USECASE_AUDIO_DIRECT_PCM_OFFLOAD:
         needs_event = true;
         break;
     /* concurrent playback in low latency allowed */
@@ -3842,11 +3912,22 @@
     return fragment_size;
 }
 
+bool platform_use_small_buffer(audio_offload_info_t* info)
+{
+    return OFFLOAD_USE_SMALL_BUFFER;
+}
+
 int platform_is_external_codec (char *snd_card_name)
 {
 
     if (!strncmp(snd_card_name, "msm8952-tomtom-snd-card",
         sizeof("msm8952-tomtom-snd-card")) ||
+        !strncmp(snd_card_name, "msm8952-tasha-snd-card",
+        sizeof("msm8952-tasha-snd-card")) ||
+        !strncmp(snd_card_name, "msm8952-tashalite-snd-card",
+        sizeof("msm8952-tashalite-snd-card")) ||
+        !strncmp(snd_card_name, "msm8952-tasha-skun-snd-card",
+        sizeof("msm8952-tasha-skun-snd-card")) ||
         !strncmp(snd_card_name, "msm8976-tasha-snd-card",
         sizeof("msm8976-tasha-snd-card")) ||
         !strncmp(snd_card_name, "msm8976-tashalite-snd-card",
@@ -4082,7 +4163,6 @@
     }
 
 
-
     ALOGI("%s Codec selected backend: %d updated bit width: %d and sample rate: %d",
                __func__, backend_idx, bit_width, sample_rate);
     // Force routing if the expected bitwdith or samplerate
@@ -4162,10 +4242,6 @@
 done:
     return ret;
 }
-bool platform_use_small_buffer(audio_offload_info_t* info)
-{
-    return OFFLOAD_USE_SMALL_BUFFER;
-}
 
 void platform_get_device_to_be_id_map(int **device_to_be_id, int *length)
 {
@@ -4313,12 +4389,10 @@
     }
     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__);
         goto fail;
     }
-
     my_data->edid_valid = true;
     return 0;
 fail:
@@ -4745,7 +4819,7 @@
     return ret;
 }
 
-/*
+ /*
  * This is a lookup table to map names of speaker device with respective left and right TZ names.
  * Also the tz names for a particular left or right speaker can be overriden by adding
  * corresponding entry in audio_platform_info.xml file.
@@ -4814,3 +4888,9 @@
     else
         return 0;
 }
+
+bool platform_send_gain_dep_cal(void *platform __unused,
+                                int level __unused)
+{
+    return 0;
+}
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 40b34bc..c4d0b59 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -253,8 +253,6 @@
 #define SPKR_PROT_CALIB_TX_PCM_DEVICE 26
 #define PLAYBACK_OFFLOAD_DEVICE 9
 #define PLAYBACK_OFFLOAD_DEVICE2 24
-
-
 #define COMPRESS_VOIP_CALL_PCM_DEVICE 3
 
 /* Define macro for Internal FM volume mixer */
@@ -271,6 +269,12 @@
 #define QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC 28
 #define VOWLAN_CALL_PCM_DEVICE 16
 
+#define VOICEMMODE1_CALL_PCM_DEVICE 26
+#define VOICEMMODE2_CALL_PCM_DEVICE 27
+
+#define VOICEMMODE1_CALL_PCM_DEVICE_OF_EXT_CODEC 29
+#define VOICEMMODE2_CALL_PCM_DEVICE_OF_EXT_CODEC 30
+
 #define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
 #define AFE_PROXY_RECORD_PCM_DEVICE 8
 
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index d8801ab..23e3095 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -382,7 +382,8 @@
     return 0;
 }
 
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device, struct audio_usecase *usecase)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+                               struct audio_usecase *usecase __unused)
 {
     if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
         strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
@@ -497,6 +498,9 @@
     if (usecase->type == PCM_PLAYBACK)
         snd_device = platform_get_output_snd_device(adev->platform,
                                             usecase->stream.out->devices);
+    else if ((usecase->type == PCM_CAPTURE) &&
+                   voice_is_in_call_rec_stream(usecase->stream.in))
+        snd_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
         snd_device = platform_get_input_snd_device(adev->platform,
                                             adev->primary_output->devices);
@@ -1175,13 +1179,13 @@
     return -ENOSYS;
 }
 
-int platform_set_spkr_device_tz_names(snd_device_t index,
-                                      const char *spkr_1_tz_name, const char *spkr_2_tz_name)
-{
-    return -ENOSYS;
-}
-
-int platform_get_wsa_mode(void *adev)
+bool platform_send_gain_dep_cal(void *platform __unused,
+                                int level __unused)
 {
     return 0;
 }
+
+void platform_set_gsm_mode(void *platform __unused, bool enable __unused)
+{
+    ALOGE("%s: Not implemented", __func__);
+}
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index c96d11e..5bf6ae4 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, 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
@@ -87,9 +87,6 @@
     SND_DEVICE_IN_HANDSET_MIC,
 };
 
-static const snd_device_t tomtom_8996_CDP_variant_devices[] = {
-};
-
 static const snd_device_t tomtom_liquid_variant_devices[] = {
     SND_DEVICE_OUT_SPEAKER,
     SND_DEVICE_OUT_SPEAKER_EXTERNAL_1,
@@ -134,6 +131,10 @@
     SND_DEVICE_IN_HANDSET_MIC_EXTERNAL
 };
 
+static const snd_device_t tasha_DB_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER
+};
+
 static const snd_device_t taiko_apq8084_sbc_variant_devices[] = {
     SND_DEVICE_IN_HANDSET_MIC,
     SND_DEVICE_IN_SPEAKER_MIC,
@@ -171,6 +172,34 @@
     SND_DEVICE_OUT_VOICE_SPEAKER,
 };
 
+static const snd_device_t tasha_fluid_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+    SND_DEVICE_OUT_VOICE_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+    SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET,
+    SND_DEVICE_OUT_SPEAKER_PROTECTED,
+    SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+};
+
+static const snd_device_t tasha_liquid_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_EXTERNAL_1,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+    SND_DEVICE_IN_SPEAKER_MIC,
+    SND_DEVICE_IN_HEADSET_MIC,
+    SND_DEVICE_IN_VOICE_DMIC,
+    SND_DEVICE_IN_VOICE_SPEAKER_DMIC,
+    SND_DEVICE_IN_VOICE_REC_DMIC_STEREO,
+    SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE,
+    SND_DEVICE_IN_QUAD_MIC,
+    SND_DEVICE_IN_HANDSET_STEREO_DMIC,
+    SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
+};
+
 static void  update_hardware_info_8084(struct hardware_info *hw_info, const char *snd_card_name)
 {
     if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card") ||
@@ -254,30 +283,24 @@
 
 static void  update_hardware_info_8996(struct hardware_info *hw_info, const char *snd_card_name)
 {
-    if (!strcmp(snd_card_name, "msm8996-tomtom-mtp-snd-card")) {
-        strlcpy(hw_info->type, " mtp", sizeof(hw_info->type));
+    if (!strcmp(snd_card_name, "msm8996-tasha-fluid-snd-card")) {
+        strlcpy(hw_info->type, " fluid", sizeof(hw_info->type));
         strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
-        hw_info->snd_devices = NULL;
-        hw_info->num_snd_devices = 0;
-        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
-    } else if (!strcmp(snd_card_name, "msm8996-tomtom-cdp-snd-card")) {
-        strlcpy(hw_info->type, " cdp", sizeof(hw_info->type));
-        strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
-        hw_info->snd_devices = (snd_device_t *)tomtom_8996_CDP_variant_devices;
-        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_8996_CDP_variant_devices);
-        strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn));
-    } else if (!strcmp(snd_card_name, "msm8996-tomtom-stp-snd-card")) {
-        strlcpy(hw_info->type, " stp", sizeof(hw_info->type));
-        strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
-        hw_info->snd_devices = (snd_device_t *)tomtom_stp_variant_devices;
-        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_stp_variant_devices);
-        strlcpy(hw_info->dev_extn, "-stp", sizeof(hw_info->dev_extn));
-    } else if (!strcmp(snd_card_name, "msm8996-tomtom-liquid-snd-card")) {
+        hw_info->snd_devices = (snd_device_t *)tasha_fluid_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tasha_fluid_variant_devices);
+        strlcpy(hw_info->dev_extn, "-fluid", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8996-tasha-liquid-snd-card")) {
         strlcpy(hw_info->type, " liquid", sizeof(hw_info->type));
         strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
-        hw_info->snd_devices = (snd_device_t *)tomtom_liquid_variant_devices;
-        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_liquid_variant_devices);
+        hw_info->snd_devices = (snd_device_t *)tasha_liquid_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tasha_liquid_variant_devices);
         strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8996-tasha-db-snd-card")) {
+        strlcpy(hw_info->type, " dragon-board", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
+        hw_info->snd_devices = (snd_device_t *)tasha_DB_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tasha_DB_variant_devices);
+        strlcpy(hw_info->dev_extn, "-db", sizeof(hw_info->dev_extn));
     } else {
         ALOGW("%s: Not a 8996 device", __func__);
     }
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6f48828..d4cdf2e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -54,6 +54,7 @@
 
 #define PLATFORM_INFO_XML_PATH      "/system/etc/audio_platform_info.xml"
 #define PLATFORM_INFO_XML_PATH_I2S  "/system/etc/audio_platform_info_i2s.xml"
+#include <linux/msm_audio.h>
 
 #define LIB_ACDB_LOADER "libacdbloader.so"
 #define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
@@ -98,7 +99,8 @@
 #define EDID_FORMAT_LPCM    1
 
 /* fallback app type if the default app type from acdb loader fails */
-#define DEFAULT_APP_TYPE  0x11130
+#define DEFAULT_APP_TYPE_RX_PATH  0x11130
+#define DEFAULT_APP_TYPE_TX_PATH  0x11132
 
 /* Retry for delay in FW loading*/
 #define RETRY_NUMBER 10
@@ -117,6 +119,7 @@
 #define AUDIO_PARAMETER_KEY_AUD_CALDATA   "cal_data"
 #define AUDIO_PARAMETER_KEY_AUD_CALRESULT "cal_result"
 
+#define AUDIO_PARAMETER_KEY_PERF_LOCK_OPTS "perf_lock_opts"
 
 /* Query external audio device connection status */
 #define AUDIO_PARAMETER_KEY_EXT_AUDIO_DEVICE "ext_audio_device"
@@ -129,6 +132,7 @@
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_ANC_CAL] = "anc_cal",
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
+        [WCD9XXX_VBAT_CAL] = "vbat_cal",
 };
 
 #define  AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED  "is_hw_dec_session_allowed"
@@ -167,6 +171,12 @@
     uint32_t             param_id;
 } acdb_audio_cal_cfg_t;
 
+enum {
+    CAL_MODE_SEND           = 0x1,
+    CAL_MODE_PERSIST        = 0x2,
+    CAL_MODE_RTAC           = 0x4
+};
+
 /* Audio calibration related functions */
 typedef void (*acdb_deallocate_t)();
 typedef int  (*acdb_init_t)(const char *, char *, int);
@@ -178,6 +188,8 @@
 acdb_loader_get_calibration_t acdb_loader_get_calibration;
 typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
 typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
+typedef int (*acdb_send_common_top_t) (void);
+typedef int (*acdb_set_codec_data_t) (void *, char *);
 
 typedef struct codec_backend_cfg {
     uint32_t sample_rate;
@@ -190,8 +202,8 @@
     bool platform_na_prop_enabled;
     bool ui_na_prop_enabled;
 } native_audio_prop;
-
 static native_audio_prop na_props = {0, 0};
+typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
 
 struct platform_data {
     struct audio_device *adev;
@@ -210,6 +222,9 @@
     bool ec_ref_enabled;
     bool is_i2s_ext_modem;
     bool is_acdb_initialized;
+    /* Vbat monitor related flags */
+    bool is_vbat_speaker;
+    bool gsm_mode_enabled;
     /* Audio calibration related functions */
     void                       *acdb_handle;
     int                        voice_feature_set;
@@ -221,8 +236,11 @@
     acdb_send_voice_cal_t      acdb_send_voice_cal;
     acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
     acdb_get_default_app_type_t acdb_get_default_app_type;
+    acdb_send_common_top_t     acdb_send_common_top;
+    acdb_set_codec_data_t      acdb_set_codec_data;
 
     void *hw_info;
+    acdb_send_gain_dep_cal_t   acdb_send_gain_dep_cal;
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
@@ -235,11 +253,12 @@
                                             DEEP_BUFFER_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
                                            LOWLATENCY_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_ULL]         = {MULTIMEDIA3_PCM_DEVICE,
+                                            MULTIMEDIA3_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
                                          MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     [USECASE_AUDIO_PLAYBACK_OFFLOAD2] =
                      {PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD3] =
@@ -256,12 +275,7 @@
                      {PLAYBACK_OFFLOAD_DEVICE8, PLAYBACK_OFFLOAD_DEVICE8},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] =
                      {PLAYBACK_OFFLOAD_DEVICE9, PLAYBACK_OFFLOAD_DEVICE9},
-#endif
-    [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE,
-                                    MULTIMEDIA3_PCM_DEVICE},
 
-    [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] =
-                     {PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2},
 
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
@@ -316,15 +330,20 @@
     [SND_DEVICE_OUT_SPEAKER] = "speaker",
     [SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = "speaker-ext-1",
     [SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
+    [SND_DEVICE_OUT_SPEAKER_VBAT] = "speaker-vbat",
     [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
     [SND_DEVICE_OUT_HEADPHONES] = "headphones",
     [SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
+    [SND_DEVICE_OUT_LINE] = "line",
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
+    [SND_DEVICE_OUT_SPEAKER_AND_LINE] = "speaker-and-line",
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = "speaker-and-headphones-ext-1",
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = "speaker-and-headphones-ext-2",
     [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
     [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
+    [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = "voice-speaker-vbat",
     [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
+    [SND_DEVICE_OUT_VOICE_LINE] = "voice-line",
     [SND_DEVICE_OUT_HDMI] = "hdmi",
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
@@ -345,6 +364,8 @@
     [SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
     [SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected",
     [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = "voice-speaker-protected",
+    [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = "speaker-protected-vbat",
+    [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = "voice-speaker-protected-vbat",
 
     /* Capture sound devices */
     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -414,15 +435,20 @@
     [SND_DEVICE_OUT_SPEAKER] = 14,
     [SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 130,
     [SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 130,
+    [SND_DEVICE_OUT_SPEAKER_VBAT] = 14,
     [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
+    [SND_DEVICE_OUT_LINE] = 10,
     [SND_DEVICE_OUT_HEADPHONES] = 10,
     [SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
+    [SND_DEVICE_OUT_SPEAKER_AND_LINE] = 10,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = 130,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 130,
     [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
     [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
+    [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = 14,
     [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
+    [SND_DEVICE_OUT_VOICE_LINE] = 10,
     [SND_DEVICE_OUT_HDMI] = 18,
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
     [SND_DEVICE_OUT_BT_SCO] = 22,
@@ -443,6 +469,8 @@
     [SND_DEVICE_OUT_ANC_HANDSET] = 103,
     [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
     [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
+    [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = 124,
+    [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = 101,
 
     [SND_DEVICE_IN_HANDSET_MIC] = 4,
     [SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = 4,
@@ -514,15 +542,20 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_VBAT)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES_44_1)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_LINE)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_LINE)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_VBAT)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
+    {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_BT_SCO)},
@@ -542,6 +575,8 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HANDSET)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_EXTERNAL)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)},
@@ -602,9 +637,9 @@
 static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD2)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD3)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD4)},
@@ -613,9 +648,6 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD7)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
-#endif
-    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
-    {TO_NAME_INDEX(USECASE_AUDIO_DIRECT_PCM_OFFLOAD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
@@ -719,8 +751,80 @@
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 
+bool platform_send_gain_dep_cal(void *platform, int level) {
+    bool ret_val = false;
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    int acdb_dev_id, app_type;
+    int acdb_dev_type = MSM_SNDDEV_CAP_RX;
+    int mode = CAL_MODE_RTAC;
+    struct listnode *node;
+    struct audio_usecase *usecase;
+
+    if (my_data->acdb_send_gain_dep_cal == NULL) {
+        ALOGE("%s: dlsym error for acdb_send_gain_dep_cal", __func__);
+        return ret_val;
+    }
+
+    if (!voice_is_in_call(adev)) {
+        ALOGV("%s: Not Voice call usecase, apply new cal for level %d",
+               __func__, level);
+
+        // find the current active sound device
+        list_for_each(node, &adev->usecase_list) {
+            usecase = node_to_item(node, struct audio_usecase, list);
+
+            if (usecase != NULL &&
+                usecase->type == PCM_PLAYBACK &&
+                usecase->stream.out->devices == AUDIO_DEVICE_OUT_SPEAKER) {
+
+                ALOGV("%s: out device is %d", __func__,  usecase->out_snd_device);
+                app_type = usecase->stream.out->app_type_cfg.app_type;
+
+                if (audio_extn_spkr_prot_is_enabled()) {
+                    acdb_dev_id = audio_extn_spkr_prot_get_acdb_id(usecase->out_snd_device);
+                } else {
+                    acdb_dev_id = acdb_device_table[usecase->out_snd_device];
+                }
+
+                if (!my_data->acdb_send_gain_dep_cal(acdb_dev_id, app_type,
+                                                     acdb_dev_type, mode, level)) {
+                    // set ret_val true if at least one calibration is set successfully
+                    ret_val = true;
+                } else {
+                    ALOGE("%s: my_data->acdb_send_gain_dep_cal failed ", __func__);
+                }
+            } else {
+                ALOGW("%s: Usecase list is empty", __func__);
+            }
+        }
+    } else {
+        ALOGW("%s: Voice call in progress .. ignore setting new cal",
+              __func__);
+    }
+    return ret_val;
+}
+
+void platform_set_gsm_mode(void *platform, bool enable)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+
+    if (my_data->gsm_mode_enabled) {
+        my_data->gsm_mode_enabled = false;
+        ALOGV("%s: disabling gsm mode", __func__);
+        audio_route_reset_and_update_path(adev->audio_route, "gsm-mode");
+    }
+
+    if (enable) {
+         my_data->gsm_mode_enabled = true;
+         ALOGD("%s: enabling gsm mode", __func__);
+         audio_route_apply_and_update_path(adev->audio_route, "gsm-mode");
+    }
+}
+
 void platform_set_echo_reference(struct audio_device *adev, bool enable,
-    audio_devices_t out_device)
+                                 audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)adev->platform;
     snd_device_t snd_device = SND_DEVICE_NONE;
@@ -731,26 +835,29 @@
     if (strcmp(my_data->ec_ref_mixer_path, "")) {
         ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
         audio_route_reset_and_update_path(adev->audio_route,
-            my_data->ec_ref_mixer_path);
+                                          my_data->ec_ref_mixer_path);
     }
 
     if (enable) {
-        strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
-            sizeof(my_data->ec_ref_mixer_path));
         snd_device = platform_get_output_snd_device(adev->platform, &out);
+
         /*
          * If native audio device reference count > 0, then apply codec EC otherwise
-         * fallback to headphones if so or default
+         * fallback to Speakers with VBat if enabled or default
          */
         if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
-            platform_add_backend_name(my_data->ec_ref_mixer_path,
-                SND_DEVICE_OUT_HEADPHONES_44_1);
+            strlcpy(my_data->ec_ref_mixer_path, "echo-reference headphones-44.1",
+                    sizeof(my_data->ec_ref_mixer_path));
+        else if ((snd_device == SND_DEVICE_OUT_SPEAKER_VBAT) ||
+                 (snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT))
+            strlcpy(my_data->ec_ref_mixer_path, "echo-reference speaker-vbat",
+                    sizeof(my_data->ec_ref_mixer_path));
         else
-            platform_add_backend_name(my_data->ec_ref_mixer_path, snd_device);
+            strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
+                    sizeof(my_data->ec_ref_mixer_path));
 
         ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
-        audio_route_apply_and_update_path(adev->audio_route,
-            my_data->ec_ref_mixer_path);
+        audio_route_apply_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
     }
 }
 
@@ -955,6 +1062,7 @@
     backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
     backend_table[SND_DEVICE_OUT_HEADPHONES] = strdup("headphones");
     backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
+    backend_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("voice-speaker-vbat");
 }
 
 void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1010,44 +1118,97 @@
     void   *buff;
 };
 
-static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
+static int send_vbat_adc_data_to_acdb(struct platform_data *plat_data, char *cal_type)
 {
-    int ret = 0, type;
+    int ret = 0;
+    struct mixer_ctl *ctl;
+    uint16_t vbat_adc_data[2];
+    struct platform_data *my_data = plat_data;
+    struct audio_device *adev = my_data->adev;
+
+    const char *mixer_ctl_name = "Vbat ADC data";
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer ctl name - %s",
+               __func__, mixer_ctl_name);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    vbat_adc_data[0] = mixer_ctl_get_value(ctl, 0);
+    vbat_adc_data[1] = mixer_ctl_get_value(ctl, 1);
+
+    ALOGD("%s: Vbat ADC output values: Dcp1: %d , Dcp2: %d",
+           __func__, vbat_adc_data[0], vbat_adc_data[1]);
+
+    ret = my_data->acdb_set_codec_data(&vbat_adc_data[0], cal_type);
+
+done:
+    return ret;
+}
+
+static void send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration,
+                           struct platform_data *plat_data, int fd)
+{
+    int type;
 
     for (type = WCD9XXX_ANC_CAL; type < WCD9XXX_MAX_CAL; type++) {
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
+        int ret;
 
         /* MAD calibration is handled by sound trigger HAL, skip here */
         if (type == WCD9XXX_MAD_CAL)
             continue;
 
-        calib.get_size = 1;
-        ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
-                                                                 &calib);
-        if (ret < 0) {
-            ALOGE("%s get_calibration failed\n", __func__);
-            return ret;
+        ret = 0;
+
+        if ((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+           ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
+           if (ret < 0)
+               ALOGE("%s error in sending vbat adc data to acdb", __func__);
         }
+
+        calib.get_size = 1;
+        ret = acdb_loader_get_calibration(cal_name_info[type],
+                                          sizeof(struct param_data),
+                                          &calib);
+        if (ret < 0) {
+            ALOGE("%s: %s get_calibration size failed, err = %d\n",
+                  __func__, cal_name_info[type], ret);
+            continue;
+        }
+
         calib.get_size = 0;
         calib.buff = malloc(calib.buff_size);
+        if (!calib.buff) {
+            ALOGE("%s: %s: No Memory for size = %d\n",
+                  __func__, cal_name_info[type], calib.buff_size);
+            continue;
+        }
+
         ret = acdb_loader_get_calibration(cal_name_info[type],
                               sizeof(struct param_data), &calib);
         if (ret < 0) {
-            ALOGE("%s get_calibration failed\n", __func__);
+            ALOGE("%s: %s get_calibration failed, err = %d\n",
+                  __func__, cal_name_info[type], ret);
             free(calib.buff);
-            return ret;
+            continue;
         }
+
         codec_buffer.buffer = calib.buff;
         codec_buffer.size = calib.data_size;
         codec_buffer.cal_type = type;
         if (ioctl(fd, SNDRV_CTL_IOCTL_HWDEP_CAL_TYPE, &codec_buffer) < 0)
-            ALOGE("Failed to call ioctl  for %s err=%d",
-                                  cal_name_info[type], errno);
-        ALOGD("%s cal sent for %s", __func__, cal_name_info[type]);
+            ALOGE("%s: %s Failed to call ioctl, err=%d",
+                  __func__, cal_name_info[type], errno);
+        else
+            ALOGD("%s: %s cal sent successfully\n",
+              __func__, cal_name_info[type]);
+
         free(calib.buff);
     }
-    return ret;
 }
 
 static void audio_hwdep_send_cal(struct platform_data *plat_data)
@@ -1068,11 +1229,11 @@
            dlerror());
         return;
     }
-    if (send_codec_cal(acdb_loader_get_calibration, fd) < 0)
-        ALOGE("%s: Could not send anc cal", __FUNCTION__);
+
+    send_codec_cal(acdb_loader_get_calibration, plat_data, fd);
 }
 
-int platform_acdb_init(void *platform)
+static int platform_acdb_init(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     char *cvd_version = NULL;
@@ -1109,14 +1270,12 @@
     char baseband[PROPERTY_VALUE_MAX];
     char value[PROPERTY_VALUE_MAX];
     struct platform_data *my_data = NULL;
-    int retry_num = 0, snd_card_num = 0, key = 0, ret = 0;
-    const char *snd_card_name;
+    int retry_num = 0, snd_card_num = 0, key = 0;
+    const char *snd_card_name = NULL;
     char *cvd_version = NULL;
     char *snd_internal_name = NULL;
     char *tmp = NULL;
     char mixer_xml_file[MIXER_PATH_MAX_LENGTH]= {0};
-    const char *mixer_ctl_name = "Set HPX ActiveBe";
-    struct mixer_ctl *ctl = NULL;
     int idx;
 
     my_data = calloc(1, sizeof(struct platform_data));
@@ -1143,7 +1302,12 @@
             continue;
         }
 
-        snd_card_name = mixer_get_name(adev->mixer);
+        snd_card_name = strdup(mixer_get_name(adev->mixer));
+        if (!snd_card_name) {
+            ALOGE("failed to allocate memory for snd_card_name\n");
+            free(my_data);
+            return NULL;
+        }
         ALOGV("%s: snd_card_name: %s", __func__, snd_card_name);
 
         my_data->hw_info = hw_info_init(snd_card_name);
@@ -1205,6 +1369,7 @@
                 ALOGE("%s: Failed to init audio route controls, aborting.",
                        __func__);
                 free(my_data);
+                free(snd_card_name);
                 return NULL;
             }
             adev->snd_card = snd_card_num;
@@ -1218,6 +1383,8 @@
     if (snd_card_num >= MAX_SND_CARD) {
         ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
         free(my_data);
+        if (snd_card_name)
+            free(snd_card_name);
         return NULL;
     }
 
@@ -1271,6 +1438,12 @@
         }
     }
 
+    /* Check if Vbat speaker enabled property is set, this should be done before acdb init */
+    bool ret = false;
+    ret = audio_extn_can_use_vbat();
+    if (ret)
+        my_data->is_vbat_speaker = true;
+
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
     if (my_data->acdb_handle == NULL) {
@@ -1320,6 +1493,27 @@
             ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
                   __func__, LIB_ACDB_LOADER);
 
+        my_data->acdb_send_gain_dep_cal = (acdb_send_gain_dep_cal_t)dlsym(my_data->acdb_handle,
+                                                    "acdb_loader_send_gain_dep_cal");
+        if (!my_data->acdb_send_gain_dep_cal)
+            ALOGV("%s: Could not find the symbol acdb_loader_send_gain_dep_cal from %s",
+                  __func__, LIB_ACDB_LOADER);
+
+        my_data->acdb_send_common_top = (acdb_send_common_top_t)dlsym(
+                                                    my_data->acdb_handle,
+                                                    "acdb_loader_send_common_custom_topology");
+        if (!my_data->acdb_send_common_top)
+            ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+                  __func__, LIB_ACDB_LOADER);
+
+        my_data->acdb_set_codec_data = (acdb_set_codec_data_t)dlsym(
+                                                    my_data->acdb_handle,
+                                                    "acdb_loader_set_codec_data");
+        if (!my_data->acdb_set_codec_data)
+            ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+                  __func__, LIB_ACDB_LOADER);
+
+
         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_init_v2");
         if (my_data->acdb_init == NULL) {
@@ -1330,22 +1524,15 @@
         platform_acdb_init(my_data);
     }
 
-    /* Configure active back end for HPX*/
-    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
-    if (ctl) {
-        ALOGI(" sending HPX Active BE information ");
-        mixer_ctl_set_value(ctl, 0, true);
-    }
-
 acdb_init_fail:
 
     set_platform_defaults();
 
     /* Initialize ACDB ID's */
     if (my_data->is_i2s_ext_modem)
-        platform_info_init(PLATFORM_INFO_XML_PATH_I2S);
+        platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data);
     else
-        platform_info_init(PLATFORM_INFO_XML_PATH);
+        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
 
     /* If platform is apq8084 and baseband is MDM, load CSD Client specific
      * symbols. Voice call is handled by MDM and apps processor talks to
@@ -1373,7 +1560,6 @@
     audio_extn_spkr_prot_init(adev);
 
     audio_extn_dolby_set_license(adev);
-    audio_hwdep_send_cal(my_data);
 
     /* init audio device arbitration */
     audio_extn_dev_arbi_init();
@@ -1397,6 +1583,7 @@
         strdup("SLIM_5_RX SampleRate");
 
     my_data->edid_info = NULL;
+    free(snd_card_name);
     return my_data;
 }
 
@@ -1434,13 +1621,27 @@
     audio_extn_dap_hal_deinit();
 }
 
-int platform_is_acdb_initialized(void *platform)
+static int platform_is_acdb_initialized(void *platform)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     ALOGD("%s: acdb initialized %d\n", __func__, my_data->is_acdb_initialized);
     return my_data->is_acdb_initialized;
 }
 
+void platform_snd_card_update(void *platform, int snd_scard_state)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (snd_scard_state == SND_CARD_STATE_ONLINE) {
+        if (!platform_is_acdb_initialized(my_data)) {
+            if(platform_acdb_init(my_data))
+                ALOGE("%s: acdb initialization is failed", __func__);
+        } else if (my_data->acdb_send_common_top() < 0) {
+                ALOGD("%s: acdb did not set common topology", __func__);
+        }
+    }
+}
+
 const char *platform_get_snd_device_name(snd_device_t snd_device)
 {
     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
@@ -1449,22 +1650,6 @@
         return "";
 }
 
-const char *platform_get_spkr_1_tz_name(snd_device_t snd_device)
-{
-    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
-        return speaker_device_tz_names.spkr_1_tz_name;
-    else
-        return "";
-}
-
-const char *platform_get_spkr_2_tz_name(snd_device_t snd_device)
-{
-    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
-        return speaker_device_tz_names.spkr_2_tz_name;
-    else
-        return "";
-}
-
 int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
                                       char *device_name)
 {
@@ -1481,13 +1666,20 @@
     return 0;
 }
 
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device, struct audio_usecase *usecase)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+                               struct audio_usecase *usecase)
 {
     if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
         ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
         return;
     }
 
+    if ((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+        !(usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)) {
+        ALOGI("%s: Not adding vbat speaker device to non voice use cases", __func__);
+        return;
+    }
+
     const char * suffix = backend_table[snd_device];
 
     if (suffix != NULL) {
@@ -1631,7 +1823,15 @@
     if (my_data->acdb_get_default_app_type)
         return my_data->acdb_get_default_app_type();
     else
-        return DEFAULT_APP_TYPE;
+        return DEFAULT_APP_TYPE_RX_PATH;
+}
+
+int platform_get_default_app_type_v2(void *platform, usecase_type_t  type)
+{
+    if(type == PCM_CAPTURE)
+        return DEFAULT_APP_TYPE_TX_PATH;
+    else
+        return DEFAULT_APP_TYPE_RX_PATH;
 }
 
 int platform_get_snd_device_acdb_id(snd_device_t snd_device)
@@ -1670,11 +1870,12 @@
 
 int platform_set_native_support(bool codec_support)
 {
+    int ret = 0;
     na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled
         = codec_support;
     ALOGD("%s: na_props.platform_na_prop_enabled: %d", __func__,
            na_props.platform_na_prop_enabled);
-    return 0;
+    return ret;
 }
 
 int platform_get_native_support()
@@ -1788,11 +1989,13 @@
     int snd_device = SND_DEVICE_OUT_SPEAKER;
 
     if (usecase->type == PCM_PLAYBACK)
-        snd_device = platform_get_output_snd_device(adev->platform,
-                                            usecase->stream.out);
+        snd_device =  usecase->out_snd_device;
+    else if ((usecase->type == PCM_CAPTURE) &&
+                   voice_is_in_call_rec_stream(usecase->stream.in))
+        snd_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
-        snd_device = platform_get_input_snd_device(adev->platform,
-                                            adev->primary_output->devices);
+        snd_device = usecase->in_snd_device;
+
     acdb_dev_id = acdb_device_table[audio_extn_get_spkr_prot_snd_device(snd_device)];
     if (acdb_dev_id < 0) {
         ALOGE("%s: Could not find acdb id for device(%d)",
@@ -1841,10 +2044,14 @@
     if (my_data->csd == NULL)
         return ret;
 
-    if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
-        audio_extn_spkr_prot_is_enabled())
-        acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
-    else
+    if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+         out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+         audio_extn_spkr_prot_is_enabled()) {
+        if (my_data->is_vbat_speaker)
+            acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+        else
+            acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+    } else
         acdb_rx_id = acdb_device_table[out_snd_device];
 
     acdb_tx_id = acdb_device_table[in_snd_device];
@@ -1901,10 +2108,14 @@
     if (my_data->csd == NULL)
         return ret;
 
-    if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
-        audio_extn_spkr_prot_is_enabled())
-        acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
-    else
+    if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+         out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+         audio_extn_spkr_prot_is_enabled()) {
+        if (my_data->is_vbat_speaker)
+            acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+         else
+            acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+    } else
         acdb_rx_id = acdb_device_table[out_snd_device];
 
     acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2109,6 +2320,9 @@
                 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2;
             else
                 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
+        } else if (devices == (AUDIO_DEVICE_OUT_LINE |
+                               AUDIO_DEVICE_OUT_SPEAKER)) {
+            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;
@@ -2132,7 +2346,8 @@
     if ((mode == AUDIO_MODE_IN_CALL) ||
         voice_extn_compress_voip_is_active(adev)) {
         if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
-            devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
+            devices & AUDIO_DEVICE_OUT_WIRED_HEADSET ||
+            devices & AUDIO_DEVICE_OUT_LINE) {
             if ((adev->voice.tty_mode != TTY_MODE_OFF) &&
                 !voice_extn_compress_voip_is_active(adev)) {
                 switch (adev->voice.tty_mode) {
@@ -2149,6 +2364,8 @@
                     ALOGE("%s: Invalid TTY mode (%#x)",
                           __func__, adev->voice.tty_mode);
                 }
+            } else if (devices & AUDIO_DEVICE_OUT_LINE) {
+                snd_device = SND_DEVICE_OUT_VOICE_LINE;
             } else if (audio_extn_get_anc_enabled()) {
                 if (audio_extn_should_use_fb_anc())
                     snd_device = SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET;
@@ -2163,7 +2380,10 @@
             else
                 snd_device = SND_DEVICE_OUT_BT_SCO;
         } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
-            snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
+                if (my_data->is_vbat_speaker)
+                    snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_VBAT;
+                else
+                    snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
         } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
                    devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
             snd_device = SND_DEVICE_OUT_USB_HEADSET;
@@ -2195,6 +2415,8 @@
                 snd_device = SND_DEVICE_OUT_HEADPHONES_44_1;
           else
                 snd_device = SND_DEVICE_OUT_HEADPHONES;
+    } else if (devices & AUDIO_DEVICE_OUT_LINE) {
+        snd_device = SND_DEVICE_OUT_LINE;
     } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
         if (my_data->external_spk_1)
             snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_1;
@@ -2202,6 +2424,8 @@
             snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_2;
         else if (adev->speaker_lr_swap)
             snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
+        else if (my_data->is_vbat_speaker)
+            snd_device = SND_DEVICE_OUT_SPEAKER_VBAT;
         else
             snd_device = SND_DEVICE_OUT_SPEAKER;
     } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
@@ -2272,7 +2496,8 @@
         if ((adev->voice.tty_mode != TTY_MODE_OFF) &&
             !voice_extn_compress_voip_is_active(adev)) {
             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
-                out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
+                out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET ||
+                out_device & AUDIO_DEVICE_OUT_LINE) {
                 switch (adev->voice.tty_mode) {
                 case TTY_MODE_FULL:
                     snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
@@ -2290,7 +2515,8 @@
             }
         }
         if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
-            out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
+            out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+                out_device & AUDIO_DEVICE_OUT_LINE) {
             if (out_device & AUDIO_DEVICE_OUT_EARPIECE &&
                 audio_extn_should_use_handset_anc(channel_count)) {
                 snd_device = SND_DEVICE_IN_AANC_HANDSET_MIC;
@@ -2503,7 +2729,8 @@
                 snd_device = SND_DEVICE_IN_SPEAKER_STEREO_DMIC;
             else
                 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
-        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
+        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+                        out_device & AUDIO_DEVICE_OUT_LINE) {
             snd_device = SND_DEVICE_IN_HANDSET_MIC;
         } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
             if (adev->bt_wb_speech_enabled) {
@@ -2804,6 +3031,44 @@
         free(dptr);
 }
 
+static void perf_lock_set_params(struct platform_data *platform,
+                          struct str_parms *parms,
+                          char *value, int len)
+{
+    int err = 0, i = 0, num_opts = 0;
+    char *test_r = NULL;
+    char *opts = NULL;
+    char *opts_size = NULL;
+
+    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_PERF_LOCK_OPTS,
+                            value, len);
+    if (err >= 0) {
+        opts_size = strtok_r(value, ", ", &test_r);
+        if (opts_size == NULL) {
+            ALOGE("%s: incorrect perf lock opts\n", __func__);
+            return;
+        }
+        num_opts = atoi(opts_size);
+        if (num_opts > 0) {
+            if (num_opts > MAX_PERF_LOCK_OPTS) {
+                ALOGD("%s: num_opts %d exceeds max %d, setting to max\n",
+                      __func__, num_opts, MAX_PERF_LOCK_OPTS);
+                num_opts = MAX_PERF_LOCK_OPTS;
+            }
+            for (i = 0; i < num_opts; i++) {
+                opts = strtok_r(NULL, ", ", &test_r);
+                if (opts == NULL) {
+                    ALOGE("%s: incorrect perf lock opts\n", __func__);
+                    break;
+                }
+                platform->adev->perf_lock_opts[i] = strtoul(opts, NULL, 16);
+            }
+            platform->adev->perf_lock_opts_size = i;
+        }
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_PERF_LOCK_OPTS);
+    }
+}
+
 int platform_set_parameters(void *platform, struct str_parms *parms)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -2901,6 +3166,8 @@
     /* handle audio calibration parameters */
     set_audiocal(platform, parms, value, len);
     native_audio_set_params(platform, parms, value, len);
+    audio_extn_spkr_prot_set_parameters(parms, value, len);
+    perf_lock_set_params(platform, parms, value, len);
 done:
     ALOGV("%s: exit with code(%d)", __func__, ret);
     if(kv_pairs != NULL)
@@ -3114,6 +3381,8 @@
     char value[512] = {0};
     int ret;
     char *kv_pairs = NULL;
+    char propValue[PROPERTY_VALUE_MAX]={0};
+    bool prop_playback_enabled = false;
 
     ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK,
                             value, sizeof(value));
@@ -3197,7 +3466,7 @@
 int platform_update_usecase_from_source(int source, int usecase)
 {
     ALOGV("%s: input source :%d", __func__, source);
-    if(source == AUDIO_SOURCE_FM_TUNER)
+    if (source == AUDIO_SOURCE_FM_TUNER)
         usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
     return usecase;
 }
@@ -3421,7 +3690,6 @@
     struct stream_out *out = NULL;
     unsigned int bit_width;
     unsigned int sample_rate;
-    char value[PROPERTY_VALUE_MAX] = {0};
     int backend_idx = DEFAULT_CODEC_BACKEND;
     int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
@@ -3476,6 +3744,7 @@
             }
         }
     }
+
     if (backend_idx != HEADPHONE_44_1_BACKEND) {
         // 16 bit playbacks are allowed through 16 bit/48 khz backend only for
         // all non-native streams
@@ -3484,20 +3753,6 @@
             ALOGD("%s: resetting sample_rate back to default, "
                    "backend_idx: %d", __func__, backend_idx);
         }
-
-        //check if mulitchannel clip needs to be down sampled  to 48k
-        property_get("audio.playback.mch.downsample",value,"");
-        if (!strncmp("true", value, sizeof("true"))) {
-            out = usecase->stream.out;
-            if ((popcount(out->channel_mask) > 2) &&
-                          (out->sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
-                          !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)) {
-                /* update out sample rate to reflect current backend sample rate  */
-                sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-                ALOGD("%s: MCH session defaulting sample rate to %d",
-                     __func__, sample_rate);
-            }
-        }
         // 24 bit playback on speakers is allowed through 48 khz backend only
         // bit width re-configured based on platform info
         if ((24 == bit_width) &&
@@ -4093,15 +4348,6 @@
 }
 
 /*
- * This is a lookup table to map names of speaker device with respective left and right TZ names.
- * Also the tz names for a particular left or right speaker can be overriden by adding
- * corresponding entry in audio_platform_info.xml file.
- */
-struct speaker_device_to_tz_names speaker_device_tz_names = {
-    {SND_DEVICE_OUT_SPEAKER, "", ""},
-};
-
-/*
  * This is a lookup table to map android audio input device to audio h/w interface (backend).
  * The table can be extended for other input devices by adding appropriate entries.
  * Also the audio interface for a particular input device can be overriden by adding
@@ -4153,37 +4399,4 @@
     return ret;
 }
 
-int platform_set_spkr_device_tz_names(snd_device_t index,
-                                      const char *spkr_1_tz_name, const char *spkr_2_tz_name)
-{
-    int ret = 0;
-    int i;
 
-    if (spkr_1_tz_name == NULL && spkr_2_tz_name == NULL) {
-        ALOGE("%s: Invalid input", __func__);
-        ret = -EINVAL;
-        goto done;
-    }
-    if (index != speaker_device_tz_names.snd_device) {
-        ALOGE("%s: not matching speaker device\n");
-        ret = -EINVAL;
-        goto done;
-    }
-    ALOGD("%s: Enter, spkr_1_tz_name :%s, spkr_2_tz_name:%s",
-           __func__, spkr_1_tz_name, spkr_2_tz_name);
-
-    if (spkr_1_tz_name != NULL)
-        strlcpy(speaker_device_tz_names.spkr_1_tz_name, spkr_1_tz_name,
-                sizeof(speaker_device_tz_names.spkr_1_tz_name));
-
-    if (spkr_2_tz_name != NULL)
-        strlcpy(speaker_device_tz_names.spkr_2_tz_name, spkr_2_tz_name,
-                sizeof(speaker_device_tz_names.spkr_2_tz_name));
-done:
-    return ret;
-}
-
-int platform_get_wsa_mode (void *adev)
-{
-    return 0;
-}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index fdf3400..c98d1af 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -43,7 +43,8 @@
  */
 #define AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND \
     (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
-     AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
+     AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE | \
+     AUDIO_DEVICE_OUT_LINE)
 
 /*
  * Below are the input devices for which back end is same, SLIMBUS_0_TX.
@@ -69,14 +70,19 @@
     SND_DEVICE_OUT_SPEAKER_EXTERNAL_1,
     SND_DEVICE_OUT_SPEAKER_EXTERNAL_2,
     SND_DEVICE_OUT_SPEAKER_REVERSE,
+    SND_DEVICE_OUT_SPEAKER_VBAT,
+    SND_DEVICE_OUT_LINE,
     SND_DEVICE_OUT_HEADPHONES,
     SND_DEVICE_OUT_HEADPHONES_44_1,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_LINE,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2,
     SND_DEVICE_OUT_VOICE_HANDSET,
     SND_DEVICE_OUT_VOICE_SPEAKER,
+    SND_DEVICE_OUT_VOICE_SPEAKER_VBAT,
     SND_DEVICE_OUT_VOICE_HEADPHONES,
+    SND_DEVICE_OUT_VOICE_LINE,
     SND_DEVICE_OUT_HDMI,
     SND_DEVICE_OUT_SPEAKER_AND_HDMI,
     SND_DEVICE_OUT_BT_SCO,
@@ -97,6 +103,10 @@
     SND_DEVICE_OUT_ANC_HANDSET,
     SND_DEVICE_OUT_SPEAKER_PROTECTED,
     SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+    SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT,
+    SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT,
+    SND_DEVICE_OUT_SPEAKER_WSA,
+    SND_DEVICE_OUT_VOICE_SPEAKER_WSA,
     SND_DEVICE_OUT_END,
 
     /*
@@ -194,8 +204,8 @@
  * We should take care of returning proper size when AudioFlinger queries for
  * the buffer size of an input/output stream
  */
-#define DEEP_BUFFER_OUTPUT_PERIOD_SIZE 960
-#define DEEP_BUFFER_OUTPUT_PERIOD_COUNT 5
+#define DEEP_BUFFER_OUTPUT_PERIOD_SIZE 1920
+#define DEEP_BUFFER_OUTPUT_PERIOD_COUNT 2
 #define LOW_LATENCY_OUTPUT_PERIOD_SIZE 240
 #define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2
 
@@ -237,14 +247,19 @@
 #define SPKR_PROT_CALIB_RX_PCM_DEVICE 5
 #ifdef PLATFORM_APQ8084
 #define SPKR_PROT_CALIB_TX_PCM_DEVICE 35
+#elif PLATFORM_MSM8996
+#define SPKR_PROT_CALIB_TX_PCM_DEVICE 42
 #else
 #define SPKR_PROT_CALIB_TX_PCM_DEVICE 25
 #endif
 #define PLAYBACK_OFFLOAD_DEVICE 9
 
-#ifdef MULTIPLE_OFFLOAD_ENABLED
-#ifdef PLATFORM_APQ8084
+// Direct_PCM
+#if defined (PLATFORM_MSM8994) || defined (PLATFORM_MSM8996) || defined (PLATFORM_APQ8084)
 #define PLAYBACK_OFFLOAD_DEVICE2 17
+#endif
+
+#ifdef PLATFORM_APQ8084
 #define PLAYBACK_OFFLOAD_DEVICE3 18
 #define PLAYBACK_OFFLOAD_DEVICE4 34
 #define PLAYBACK_OFFLOAD_DEVICE5 35
@@ -254,7 +269,6 @@
 #define PLAYBACK_OFFLOAD_DEVICE9 39
 #endif
 #if defined (PLATFORM_MSM8994) || defined (PLATFORM_MSM8996)
-#define PLAYBACK_OFFLOAD_DEVICE2 17
 #define PLAYBACK_OFFLOAD_DEVICE3 18
 #define PLAYBACK_OFFLOAD_DEVICE4 37
 #define PLAYBACK_OFFLOAD_DEVICE5 38
@@ -263,10 +277,6 @@
 #define PLAYBACK_OFFLOAD_DEVICE8 41
 #define PLAYBACK_OFFLOAD_DEVICE9 42
 #endif
-#endif
-
-// for DIRECT_PCM
-#define PLAYBACK_OFFLOAD_DEVICE2 17
 
 #define COMPRESS_VOIP_CALL_PCM_DEVICE 3
 
@@ -409,10 +419,4 @@
     char device_name[100];
     char interface_name[100];
 };
-
-struct speaker_device_to_tz_names {
-    snd_device_t snd_device;
-    char spkr_1_tz_name[100];
-    char spkr_2_tz_name[100];
-};
 #endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 9430721..a89c267 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -26,12 +26,12 @@
 
 void *platform_init(struct audio_device *adev);
 void platform_deinit(void *platform);
-int platform_is_acdb_initialized(void *platform);
-int platform_acdb_init(void *platform);
 const char *platform_get_snd_device_name(snd_device_t snd_device);
 int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
                                       char *device_name);
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device, struct audio_usecase *usecase);
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+                               struct audio_usecase *usecase);
+bool platform_send_gain_dep_cal(void *platform, int level);
 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type);
 int platform_get_snd_device_index(char *snd_device_index_name);
 int platform_set_fluence_type(void *platform, char *value);
@@ -46,6 +46,7 @@
 int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
                                     int app_type, int sample_rate);
 int platform_get_default_app_type(void *platform);
+int platform_get_default_app_type_v2(void *platform, usecase_type_t  type);
 int platform_switch_voice_call_device_pre(void *platform);
 int platform_switch_voice_call_enable_device_config(void *platform,
                                                     snd_device_t out_snd_device,
@@ -88,8 +89,10 @@
 
 int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend);
 
-/* From platform_info_parser.c */
-int platform_info_init(const char *filename);
+/* From platform_info.c */
+int platform_info_init(const char *filename, void *);
+
+void platform_snd_card_update(void *platform, int snd_scard_state);
 
 struct audio_offload_info_t;
 uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
@@ -118,10 +121,5 @@
 int platform_set_device_params(struct stream_out *out, int param, int value);
 int platform_set_audio_device_interface(const char * device_name, const char *intf_name,
                                         const char * codec_type);
-int platform_set_spkr_device_tz_names(snd_device_t index,
-                                       const char *spkr_1_tz_name, const char *spkr_2_tz_name);
-const char *platform_get_spkr_1_tz_name(snd_device_t snd_device);
-const char *platform_get_spkr_2_tz_name(snd_device_t snd_device);
-int platform_get_wsa_mode(void *adev);
 void platform_set_gsm_mode(void *platform, bool enable);
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 50e19c6..6514cb3 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -34,6 +34,7 @@
 #include <stdio.h>
 #include <expat.h>
 #include <cutils/log.h>
+#include <cutils/str_parms.h>
 #include <audio_hw.h>
 #include "platform_api.h"
 #include <platform.h>
@@ -48,6 +49,7 @@
     PCM_ID,
     BACKEND_NAME,
     INTERFACE_NAME,
+    CONFIG_PARAMS,
     TZ_NAME,
 } section_t;
 
@@ -59,6 +61,7 @@
 static void process_pcm_id(const XML_Char **attr);
 static void process_backend_name(const XML_Char **attr);
 static void process_interface_name(const XML_Char **attr);
+static void process_config_params(const XML_Char **attr);
 static void process_tz_name(const XML_Char **attr);
 static void process_root(const XML_Char **attr);
 
@@ -70,11 +73,19 @@
     [PCM_ID] = process_pcm_id,
     [BACKEND_NAME] = process_backend_name,
     [INTERFACE_NAME] = process_interface_name,
+    [CONFIG_PARAMS] = process_config_params,
     [TZ_NAME] = process_tz_name,
 };
 
 static section_t section;
 
+struct platform_info {
+    void             *platform;
+    struct str_parms *kvpairs;
+};
+
+static struct platform_info my_data;
+
 /*
  * <audio_platform_info>
  * <acdb_ids>
@@ -97,6 +108,12 @@
  * ...
  * ...
  * </interface_names>
+ * <config_params>
+ *      <param key="snd_card_name" value="msm8994-tomtom-mtp-snd-card"/>
+ *      ...
+ *      ...
+ * </config_params>
+ *
  * <tz_names>
  * <device name="???" spkr_1_tz_name="???" spkr_2_tz_name="???"/>
  * ...
@@ -115,7 +132,7 @@
     int index;
 
     if (strcmp(attr[0], "name") != 0) {
-        ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
+        ALOGE("%s: 'name' not found, no pcm_id set!", __func__);
         goto done;
     }
 
@@ -341,16 +358,34 @@
               __func__, attr[1]);
     }
 
-    ret = platform_set_spkr_device_tz_names(index, (char *)attr[3], (char *)attr[5]);
+    /*  ret = platform_set_spkr_device_tz_names(index, (char *)attr[3], (char *)attr[5]);
     if (ret < 0) {
         ALOGE("%s: Audio Interface not set!", __func__);
         goto done;
     }
+    */
 
 done:
     return;
 }
 
+static void process_config_params(const XML_Char **attr)
+{
+    if (strcmp(attr[0], "key") != 0) {
+        ALOGE("%s: 'key' not found", __func__);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "value") != 0) {
+        ALOGE("%s: 'value' not found", __func__);
+        goto done;
+    }
+
+    str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
+done:
+    return;
+}
+
 static void start_tag(void *userdata __unused, const XML_Char *tag_name,
                       const XML_Char **attr)
 {
@@ -366,6 +401,8 @@
         section = PCM_ID;
     } else if (strcmp(tag_name, "backend_names") == 0) {
         section = BACKEND_NAME;
+    } else if (strcmp(tag_name, "config_params") == 0) {
+        section = CONFIG_PARAMS;
     } else if (strcmp(tag_name, "interface_names") == 0) {
         section = INTERFACE_NAME;
     } else if (strcmp(tag_name, "tz_names") == 0) {
@@ -398,6 +435,14 @@
 
         section_process_fn fn = section_table[NATIVESUPPORT];
         fn(attr);
+    } else if (strcmp(tag_name, "param") == 0) {
+        if (section != CONFIG_PARAMS) {
+            ALOGE("param tag only supported with CONFIG_PARAMS section");
+            return;
+        }
+
+        section_process_fn fn = section_table[section];
+        fn(attr);
     }
 
     return;
@@ -413,6 +458,9 @@
         section = ROOT;
     } else if (strcmp(tag_name, "backend_names") == 0) {
         section = ROOT;
+    } else if (strcmp(tag_name, "config_params") == 0) {
+        section = ROOT;
+        platform_set_parameters(my_data.platform, my_data.kvpairs);
     } else if (strcmp(tag_name, "interface_names") == 0) {
         section = ROOT;
     } else if (strcmp(tag_name, "native_configs") == 0) {
@@ -420,7 +468,7 @@
     }
 }
 
-int platform_info_init(const char *filename)
+int platform_info_init(const char *filename, void *platform)
 {
     XML_Parser      parser;
     FILE            *file;
@@ -445,6 +493,9 @@
         goto err_close_file;
     }
 
+    my_data.platform = platform;
+    my_data.kvpairs = str_parms_create();
+
     XML_SetElementHandler(parser, start_tag, end_tag);
 
     while (1) {
diff --git a/hal/voice.c b/hal/voice.c
index bc9d5c7..4824d35 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -131,7 +131,8 @@
     }
 
     session->state.current = CALL_INACTIVE;
-    adev->voice.is_in_call = false;
+    if (adev->mode == AUDIO_MODE_NORMAL)
+        adev->voice.is_in_call = false;
 
     /* Disable sidetone only when no calls are active */
     if (!voice_is_call_state_active(adev))
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index bb1caf9..1dcf865 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -93,7 +93,7 @@
 
 static int audio_format_to_voip_mode(int format)
 {
-    int mode = 0;
+    int mode = AUDIO_FORMAT_INVALID;
 
     if (format == AUDIO_FORMAT_PCM_16_BIT) {
         mode = MODE_PCM;
@@ -702,15 +702,11 @@
 
 bool voice_extn_compress_voip_is_format_supported(audio_format_t format)
 {
-    switch (format) {
-    case AUDIO_FORMAT_PCM_16_BIT:
-        if (voice_extn_compress_voip_pcm_prop_check())
-            return true;
-        else
-            return false;
-    default:
-        return false;
-    }
+    if (format == AUDIO_FORMAT_PCM_16_BIT &&
+       voice_extn_compress_voip_pcm_prop_check())
+       return true;
+    else
+       return false;
 }
 
 bool voice_extn_compress_voip_is_config_supported(struct audio_config *config)
diff --git a/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h b/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
index a87717b..7f0a2cb 100644
--- a/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
+++ b/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
@@ -414,8 +414,8 @@
         unsigned int offset_to_frame;
         unsigned int frame_size;
         unsigned int encoded_pcm_samples;
-        unsigned int msw_ts;
         unsigned int lsw_ts;
+        unsigned int msw_ts;
         unsigned int nflags;
     } __attribute__ ((packed))ENC_META_OUT;
 
diff --git a/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h b/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h
index ed7f758..2d72eb2 100644
--- a/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h
+++ b/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h
@@ -341,8 +341,8 @@
         unsigned int offset_to_frame;
         unsigned int frame_size;
         unsigned int encoded_pcm_samples;
-        unsigned int msw_ts;
         unsigned int lsw_ts;
+        unsigned int msw_ts;
         unsigned int nflags;
     } __attribute__ ((packed))ENC_META_OUT;
 
diff --git a/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h b/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h
index 09ffb2d..f107789 100644
--- a/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h
+++ b/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h
@@ -342,8 +342,8 @@
         unsigned int offset_to_frame;
         unsigned int frame_size;
         unsigned int encoded_pcm_samples;
-        unsigned int msw_ts;
         unsigned int lsw_ts;
+        unsigned int msw_ts;
         unsigned int nflags;
     } __attribute__ ((packed))ENC_META_OUT;
 
diff --git a/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h b/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h
index 22cc9ed..83e129c 100644
--- a/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h
+++ b/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h
@@ -342,8 +342,8 @@
         unsigned int offset_to_frame;
         unsigned int frame_size;
         unsigned int encoded_pcm_samples;
-        unsigned int msw_ts;
         unsigned int lsw_ts;
+        unsigned int msw_ts;
         unsigned int nflags;
     } __attribute__ ((packed))ENC_META_OUT;
 
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index 9fb49ac..70814d8 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -52,11 +52,11 @@
 endif
 
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_SPK)),true)
-LOCAL_CFLAGS += -DAUDIO_EXTN_HDMI_SPK_ENABLED
+    LOCAL_CFLAGS += -DAUDIO_EXTN_HDMI_SPK_ENABLED
 endif
 
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true)
-LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
+    LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
 endif
 
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FM_POWER_OPT)),true)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 878c024..e48de6d 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -15,6 +15,24 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ *  (C) 2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define LOG_TAG "AudioPolicyManagerCustom"
@@ -46,6 +64,9 @@
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
 #include <policy.h>
+#ifdef DOLBY_ENABLE
+#include "DolbyAudioPolicy_impl.h"
+#endif // DOLBY_END
 
 namespace android {
 #ifdef VOICE_CONCURRENCY
@@ -246,6 +267,11 @@
         }
 
         updateDevicesAndOutputs();
+#ifdef DOLBY_ENABLE
+        // Before closing the opened outputs, update endpoint property with device capabilities
+        audio_devices_t audioOutputDevice = getDeviceForStrategy(getStrategy(AUDIO_STREAM_MUSIC), true);
+        mDolbyAudioPolicy.setEndpointSystemProperty(audioOutputDevice, mHwModules);
+#endif // DOLBY_END
         if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
             audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
             updateCallRouting(newDevice);
@@ -410,6 +436,13 @@
         return false;
     }
 
+    // Check if offload has been disabled
+    bool offloadDisabled = property_get_bool("audio.offload.disable", false);
+    if (offloadDisabled) {
+        ALOGI("offload disabled by audio.offload.disable=%d", offloadDisabled);
+        return false;
+    }
+
     char propValue[PROPERTY_VALUE_MAX];
     bool pcmOffload = false;
 #ifdef PCM_OFFLOAD_ENABLED
@@ -439,13 +472,13 @@
     }
 #endif
     if (!pcmOffload) {
-        // Check if offload has been disabled
-        if (property_get("audio.offload.disable", propValue, "0")) {
-            if (atoi(propValue) != 0) {
-                ALOGV("offload disabled by audio.offload.disable=%s", propValue );
-                return false;
-            }
+
+        bool compressedOffloadDisabled = property_get_bool("audio.offload.compress.disable", false);
+        if (compressedOffloadDisabled) {
+            ALOGI("compressed offload disabled by audio.offload.compress.disable=%d", compressedOffloadDisabled);
+            return false;
         }
+
         //check if it's multi-channel AAC (includes sub formats) and FLAC format
         if ((popcount(offloadInfo.channel_mask) > 2) &&
            (((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) ||
@@ -617,7 +650,7 @@
     /// Opens: can these line be executed after the switch of volume curves???
     // if leaving call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
-    if (isStateInCall(oldState)) {
+    if (isInCall()) {
         ALOGV("setPhoneState() in call state management: new state is %d", state);
         for (size_t j = 0; j < mOutputs.size(); j++) {
             audio_io_handle_t curOutput = mOutputs.keyAt(j);
@@ -1281,7 +1314,17 @@
 {
     audio_offload_info_t tOffloadInfo = AUDIO_INFO_INITIALIZER;
 
-    bool pcmOffloadEnabled = property_get_bool("audio.offload.track.enable", false);
+    bool offloadDisabled = property_get_bool("audio.offload.disable", false);
+    bool pcmOffloadEnabled = false;
+
+    if (offloadDisabled) {
+        ALOGI("offload disabled by audio.offload.disable=%d", offloadDisabled);
+    }
+
+    //read track offload property only if the global offload switch is off.
+    if (!offloadDisabled) {
+         pcmOffloadEnabled = property_get_bool("audio.offload.track.enable", false);
+    }
 
     if (offloadInfo == NULL && pcmOffloadEnabled) {
         tOffloadInfo.sample_rate  = samplingRate;
@@ -1293,7 +1336,7 @@
             ALOGV("found attribute .. setting usage %d ", attr->usage);
             tOffloadInfo.usage = attr->usage;
         } else {
-            ALOGD("%s:: attribute is NULL .. no usage set", __func__);
+            ALOGI("%s:: attribute is NULL .. no usage set", __func__);
         }
         offloadInfo = &tOffloadInfo;
     }
@@ -1404,8 +1447,8 @@
                 property_get("use.voice.path.for.pcm.voip", propValue, "0");
                 bool voipPcmSysPropEnabled = !strncmp("true", propValue, sizeof("true"));
                 if (voipPcmSysPropEnabled && (format == AUDIO_FORMAT_PCM_16_BIT)) {
-                    flags = (audio_output_flags_t)((flags &~AUDIO_OUTPUT_FLAG_FAST) |
-                                AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_DIRECT);
+                    flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
+                                                 AUDIO_OUTPUT_FLAG_DIRECT);
                     ALOGD("Set VoIP and Direct output flags for PCM format");
                 }
             }
@@ -1543,6 +1586,7 @@
         flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
         forced_deep = true;
     }
+
     if (stream == AUDIO_STREAM_TTS) {
         flags = AUDIO_OUTPUT_FLAG_TTS;
     }
@@ -1551,7 +1595,7 @@
     if (((flags == AUDIO_OUTPUT_FLAG_NONE) || forced_deep) &&
         (stream == AUDIO_STREAM_MUSIC) && (offloadInfo != NULL) &&
         ((offloadInfo->usage == AUDIO_USAGE_MEDIA) || (offloadInfo->usage == AUDIO_USAGE_GAME))) {
-        flags = (audio_output_flags_t)(flags|AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM);
+        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
         ALOGD("AudioCustomHAL --> Force Direct Flag .. flag (0x%x)", flags);
     }
 
@@ -1584,23 +1628,29 @@
     if (profile != 0) {
         sp<SwAudioOutputDescriptor> outputDesc = NULL;
 
-        for (size_t i = 0; i < mOutputs.size(); i++) {
-            sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-            if (!desc->isDuplicated() && (profile == desc->mProfile)) {
-                outputDesc = desc;
-                // reuse direct output if currently open and configured with same parameters
-                if ((samplingRate == outputDesc->mSamplingRate) &&
-                        (format == outputDesc->mFormat) &&
-                        (channelMask == outputDesc->mChannelMask)) {
-                    outputDesc->mDirectOpenCount++;
-                    ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
-                    return mOutputs.keyAt(i);
+        // if multiple concurrent offload decode is supported
+        // do no check for reuse and also don't close previous output if its offload
+        // previous output will be closed during track destruction
+        if (!(property_get_bool("audio.offload.multiple.enabled", false) &&
+                ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0))) {
+            for (size_t i = 0; i < mOutputs.size(); i++) {
+                sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+                if (!desc->isDuplicated() && (profile == desc->mProfile)) {
+                    outputDesc = desc;
+                    // reuse direct output if currently open and configured with same parameters
+                    if ((samplingRate == outputDesc->mSamplingRate) &&
+                            (format == outputDesc->mFormat) &&
+                            (channelMask == outputDesc->mChannelMask)) {
+                        outputDesc->mDirectOpenCount++;
+                        ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
+                        return mOutputs.keyAt(i);
+                    }
                 }
             }
-        }
-        // close direct output if currently open and configured with different parameters
-        if (outputDesc != NULL) {
-            closeOutput(outputDesc->mIoHandle);
+            // close direct output if currently open and configured with different parameters
+            if (outputDesc != NULL) {
+                closeOutput(outputDesc->mIoHandle);
+            }
         }
 
         // if the selected profile is offloaded and no offload info was specified,
@@ -1667,7 +1717,23 @@
         addOutput(output, outputDesc);
         audio_io_handle_t dstOutput = getOutputForEffect();
         if (dstOutput == output) {
+#ifdef DOLBY_ENABLE
+            status_t status = mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput);
+            if (status == NO_ERROR) {
+                for (size_t i = 0; i < mEffects.size(); i++) {
+                    sp<EffectDescriptor> desc = mEffects.valueAt(i);
+                    if (desc->mSession == AUDIO_SESSION_OUTPUT_MIX) {
+                        // update the mIo member of EffectDescriptor for the global effect
+                        ALOGV("%s updating mIo", __FUNCTION__);
+                        desc->mIo = dstOutput;
+                    }
+                }
+            } else {
+                ALOGW("%s moveEffects from %d to %d failed", __FUNCTION__, srcOutput, dstOutput);
+            }
+#else // DOLBY_END
             mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput);
+#endif // LINE_ADDED_BY_DOLBY
         }
         mPreviousOutputs = mOutputs;
         ALOGV("getOutput() returns new direct output %d", output);
@@ -1971,31 +2037,31 @@
       mHdmiAudioEvent(false),
       mPrevPhoneState(0)
 {
+    char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
+    bool prop_ssr_enabled = false;
+
+    if (property_get("ro.qc.sdk.audio.ssr", ssr_enabled, NULL)) {
+        prop_ssr_enabled = atoi(ssr_enabled) || !strncmp("true", ssr_enabled, 4);
+    }
 
     for (size_t i = 0; i < mHwModules.size(); i++) {
         ALOGV("Hw module %d", i);
         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
             const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
-            ALOGV("\t Input profile ", j);
+            ALOGV("Input profile ", j);
             for (size_t k = 0; k  < inProfile->mChannelMasks.size(); k++) {
                 audio_channel_mask_t channelMask =
                     inProfile->mChannelMasks.itemAt(k);
-                ALOGV("\t\tChannel Mask %x size %d", channelMask,
+                ALOGV("Channel Mask %x size %d", channelMask,
                     inProfile->mChannelMasks.size());
                 if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
-                    char ssr_enabled[PROPERTY_VALUE_MAX]={0};
-                    if ((property_get("ro.qc.sdk.audio.ssr",
-                                   ssr_enabled, NULL) > 0) &&
-                        (!strncmp("true", ssr_enabled, 4))) {
-                            ALOGV("\t\t SSR supported, retain 5.1 channel"
-                                " in input profile");
-                    } else {
-                            ALOGE("\t\t removing AUDIO_CHANNEL_IN_5POINT1 from"
-                                " input profile as SSR(surround sound record)"
-                                " is not supported on this chipset variant");
-                            inProfile->mChannelMasks.removeItemsAt(k, 1);
-                            ALOGV("\t\t Channel Mask size now %d",
-                                inProfile->mChannelMasks.size());
+                    if (!prop_ssr_enabled) {
+                        ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
+                            " input profile as SSR(surround sound record)"
+                            " is not supported on this chipset variant");
+                        inProfile->mChannelMasks.removeItemsAt(k, 1);
+                        ALOGV("Channel Mask size now %d",
+                            inProfile->mChannelMasks.size());
                     }
                 }
             }
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 437e3b9..55d59ac 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -75,6 +75,7 @@
         // indicates to the audio policy manager that the input stops being used.
         virtual status_t stopInput(audio_io_handle_t input,
                                    audio_session_t session);
+
         virtual void closeAllInputs();
 
 protected:
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 3b9787c..28445f3 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -77,3 +77,32 @@
 
 include $(BUILD_STATIC_LIBRARY)
 endif
+
+
+################################################################################
+
+ifneq ($(filter msm8992 msm8994 msm8996 msm8952 msm8937 thorium,$(TARGET_BOARD_PLATFORM)),)
+
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -DLIB_AUDIO_HAL="/system/lib/hw/audio.primary."$(TARGET_BOARD_PLATFORM)".so"
+
+LOCAL_SRC_FILES:= \
+        volume_listener.c
+
+LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+
+LOCAL_SHARED_LIBRARIES := \
+        libcutils \
+        liblog \
+        libdl
+
+LOCAL_MODULE_RELATIVE_PATH := soundfx
+LOCAL_MODULE:= libvolumelistener
+
+LOCAL_C_INCLUDES := \
+        $(call include-path-for, audio-effects)
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 8df93cb..2bc7fad 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -38,12 +38,13 @@
 #define LOG_TAG "offload_effect_bundle"
 //#define LOG_NDEBUG 0
 
+#include <stdlib.h>
 #include <cutils/list.h>
 #include <cutils/log.h>
 #include <system/thread_defs.h>
 #include <tinyalsa/asoundlib.h>
 #include <hardware/audio_effect.h>
-#include <stdlib.h>
+
 #include "bundle.h"
 #include "hw_accelerator.h"
 #include "equalizer.h"
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index 7aef997..ab8576f 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -55,6 +55,7 @@
 #endif
 
 #include <stdbool.h>
+#include <errno.h>
 #include <cutils/log.h>
 #include <tinyalsa/asoundlib.h>
 #include <sound/audio_effects.h>
diff --git a/post_proc/effect_util.c b/post_proc/effect_util.c
index b401f6a..02911c1 100644
--- a/post_proc/effect_util.c
+++ b/post_proc/effect_util.c
@@ -16,6 +16,7 @@
 
 #include <utils/Log.h>
 #include <stdlib.h>
+#include <string.h>
 #include "effect_util.h"
 #include <string.h>
 
diff --git a/post_proc/reverb.c b/post_proc/reverb.c
index 450ce81..2e97f68 100644
--- a/post_proc/reverb.c
+++ b/post_proc/reverb.c
@@ -230,6 +230,72 @@
                                   OFFLOAD_SEND_REVERB_LEVEL);
 }
 
+uint32_t reverb_get_reverb_delay(reverb_context_t *context)
+{
+    ALOGV("%s: ctxt %p, reverb delay: %d", __func__, context,
+                          context->reverb_settings.reverbDelay);
+    return context->reverb_settings.reverbDelay;
+}
+
+void reverb_set_reverb_delay(reverb_context_t *context, uint32_t delay)
+{
+    ALOGV("%s: ctxt %p, reverb delay: %d", __func__, context, delay);
+    context->reverb_settings.reverbDelay = delay;
+    offload_reverb_set_delay(&(context->offload_reverb), delay);
+    if (context->ctl)
+        offload_reverb_send_params(context->ctl, &context->offload_reverb,
+                                   OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+                                   OFFLOAD_SEND_REVERB_DELAY);
+    if (context->hw_acc_fd > 0)
+        hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+                                  OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+                                  OFFLOAD_SEND_REVERB_DELAY);
+}
+
+int16_t reverb_get_reflections_level(reverb_context_t *context)
+{
+    ALOGV("%s: ctxt %p, reflection level: %d", __func__, context,
+                          context->reverb_settings.reflectionsLevel);
+    return context->reverb_settings.reflectionsLevel;
+}
+
+void reverb_set_reflections_level(reverb_context_t *context, int16_t level)
+{
+    ALOGV("%s: ctxt %p, reflection level: %d", __func__, context, level);
+    context->reverb_settings.reflectionsLevel = level;
+    offload_reverb_set_reflections_level(&(context->offload_reverb), level);
+    if (context->ctl)
+        offload_reverb_send_params(context->ctl, &context->offload_reverb,
+                                   OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+                                   OFFLOAD_SEND_REVERB_REFLECTIONS_LEVEL);
+    if (context->hw_acc_fd > 0)
+        hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+                                  OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+                                  OFFLOAD_SEND_REVERB_REFLECTIONS_LEVEL);
+}
+
+uint32_t reverb_get_reflections_delay(reverb_context_t *context)
+{
+    ALOGV("%s: ctxt %p, reflection delay: %d", __func__, context,
+                          context->reverb_settings.reflectionsDelay);
+    return context->reverb_settings.reflectionsDelay;
+}
+
+void reverb_set_reflections_delay(reverb_context_t *context, uint32_t delay)
+{
+    ALOGV("%s: ctxt %p, reflection delay: %d", __func__, context, delay);
+    context->reverb_settings.reflectionsDelay = delay;
+    offload_reverb_set_reflections_delay(&(context->offload_reverb), delay);
+    if (context->ctl)
+        offload_reverb_send_params(context->ctl, &context->offload_reverb,
+                                   OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+                                   OFFLOAD_SEND_REVERB_REFLECTIONS_DELAY);
+    if (context->hw_acc_fd > 0)
+        hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+                                  OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+                                  OFFLOAD_SEND_REVERB_REFLECTIONS_DELAY);
+}
+
 int16_t reverb_get_diffusion(reverb_context_t *context)
 {
     ALOGV("%s: ctxt %p, diffusion: %d", __func__, context,
@@ -305,8 +371,33 @@
     context->reverb_settings.decayTime = reverb_settings->decayTime;
     context->reverb_settings.decayHFRatio = reverb_settings->decayHFRatio;
     context->reverb_settings.reverbLevel = reverb_settings->reverbLevel;
+    context->reverb_settings.reverbDelay = reverb_settings->reverbDelay;
+    context->reverb_settings.reflectionsLevel = reverb_settings->reflectionsLevel;
+    context->reverb_settings.reflectionsDelay = reverb_settings->reflectionsDelay;
     context->reverb_settings.diffusion = reverb_settings->diffusion;
     context->reverb_settings.density = reverb_settings->density;
+
+    offload_reverb_set_room_level(&(context->offload_reverb),
+                               reverb_settings->roomLevel);
+    offload_reverb_set_room_hf_level(&(context->offload_reverb),
+                               reverb_settings->roomHFLevel);
+    offload_reverb_set_decay_time(&(context->offload_reverb),
+                               reverb_settings->decayTime);
+    offload_reverb_set_decay_hf_ratio(&(context->offload_reverb),
+                               reverb_settings->decayHFRatio);
+    offload_reverb_set_reverb_level(&(context->offload_reverb),
+                               reverb_settings->reverbLevel);
+    offload_reverb_set_delay(&(context->offload_reverb),
+                               reverb_settings->reverbDelay);
+    offload_reverb_set_reflections_level(&(context->offload_reverb),
+                               reverb_settings->reflectionsLevel);
+    offload_reverb_set_reflections_delay(&(context->offload_reverb),
+                               reverb_settings->reflectionsDelay);
+    offload_reverb_set_diffusion(&(context->offload_reverb),
+                               reverb_settings->diffusion);
+    offload_reverb_set_density(&(context->offload_reverb),
+                               reverb_settings->density);
+
     if (context->ctl)
         offload_reverb_send_params(context->ctl, &context->offload_reverb,
                                    OFFLOAD_SEND_REVERB_ENABLE_FLAG |
@@ -315,6 +406,9 @@
                                    OFFLOAD_SEND_REVERB_DECAY_TIME |
                                    OFFLOAD_SEND_REVERB_DECAY_HF_RATIO |
                                    OFFLOAD_SEND_REVERB_LEVEL |
+                                   OFFLOAD_SEND_REVERB_DELAY |
+                                   OFFLOAD_SEND_REVERB_REFLECTIONS_LEVEL |
+                                   OFFLOAD_SEND_REVERB_REFLECTIONS_DELAY |
                                    OFFLOAD_SEND_REVERB_DIFFUSION |
                                    OFFLOAD_SEND_REVERB_DENSITY);
     if (context->hw_acc_fd > 0)
@@ -325,6 +419,9 @@
                                   OFFLOAD_SEND_REVERB_DECAY_TIME |
                                   OFFLOAD_SEND_REVERB_DECAY_HF_RATIO |
                                   OFFLOAD_SEND_REVERB_LEVEL |
+                                  OFFLOAD_SEND_REVERB_DELAY |
+                                  OFFLOAD_SEND_REVERB_REFLECTIONS_LEVEL |
+                                  OFFLOAD_SEND_REVERB_REFLECTIONS_DELAY |
                                   OFFLOAD_SEND_REVERB_DIFFUSION |
                                   OFFLOAD_SEND_REVERB_DENSITY);
 }
@@ -388,16 +485,6 @@
            p->status = -EINVAL;
         p->vsize = sizeof(uint16_t);
         break;
-    case REVERB_PARAM_REFLECTIONS_LEVEL:
-        if (p->vsize < sizeof(uint16_t))
-           p->status = -EINVAL;
-        p->vsize = sizeof(uint16_t);
-        break;
-    case REVERB_PARAM_REFLECTIONS_DELAY:
-        if (p->vsize < sizeof(uint32_t))
-           p->status = -EINVAL;
-        p->vsize = sizeof(uint32_t);
-        break;
     case REVERB_PARAM_REVERB_LEVEL:
         if (p->vsize < sizeof(uint16_t))
            p->status = -EINVAL;
@@ -408,6 +495,16 @@
            p->status = -EINVAL;
         p->vsize = sizeof(uint32_t);
         break;
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+        if (p->vsize < sizeof(uint16_t))
+           p->status = -EINVAL;
+        p->vsize = sizeof(uint16_t);
+        break;
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+        if (p->vsize < sizeof(uint32_t))
+           p->status = -EINVAL;
+        p->vsize = sizeof(uint32_t);
+        break;
     case REVERB_PARAM_DIFFUSION:
         if (p->vsize < sizeof(uint16_t))
            p->status = -EINVAL;
@@ -433,19 +530,6 @@
         return 0;
 
     switch (param) {
-    case REVERB_PARAM_PROPERTIES:
-        reverb_settings = (reverb_settings_t *)value;
-        reverb_settings->roomLevel = reverb_get_room_level(reverb_ctxt);
-        reverb_settings->roomHFLevel = reverb_get_room_hf_level(reverb_ctxt);
-        reverb_settings->decayTime = reverb_get_decay_time(reverb_ctxt);
-        reverb_settings->decayHFRatio = reverb_get_decay_hf_ratio(reverb_ctxt);
-        reverb_settings->reflectionsLevel = 0;
-        reverb_settings->reflectionsDelay = 0;
-        reverb_settings->reverbDelay = 0;
-        reverb_settings->reverbLevel = reverb_get_reverb_level(reverb_ctxt);
-        reverb_settings->diffusion = reverb_get_diffusion(reverb_ctxt);
-        reverb_settings->density = reverb_get_density(reverb_ctxt);
-        break;
     case REVERB_PARAM_ROOM_LEVEL:
         *(int16_t *)value = reverb_get_room_level(reverb_ctxt);
         break;
@@ -461,20 +545,33 @@
     case REVERB_PARAM_REVERB_LEVEL:
         *(int16_t *)value = reverb_get_reverb_level(reverb_ctxt);
         break;
+    case REVERB_PARAM_REVERB_DELAY:
+        *(uint32_t *)value = reverb_get_reverb_delay(reverb_ctxt);
+        break;
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+        *(int16_t *)value = reverb_get_reflections_level(reverb_ctxt);
+        break;
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+        *(uint32_t *)value = reverb_get_reflections_delay(reverb_ctxt);
+        break;
     case REVERB_PARAM_DIFFUSION:
         *(int16_t *)value = reverb_get_diffusion(reverb_ctxt);
         break;
     case REVERB_PARAM_DENSITY:
         *(int16_t *)value = reverb_get_density(reverb_ctxt);
         break;
-    case REVERB_PARAM_REFLECTIONS_LEVEL:
-        *(uint16_t *)value = 0;
-        break;
-    case REVERB_PARAM_REFLECTIONS_DELAY:
-        *(uint32_t *)value = 0;
-        break;
-    case REVERB_PARAM_REVERB_DELAY:
-        *(uint32_t *)value = 0;
+    case REVERB_PARAM_PROPERTIES:
+        reverb_settings = (reverb_settings_t *)value;
+        reverb_settings->roomLevel = reverb_get_room_level(reverb_ctxt);
+        reverb_settings->roomHFLevel = reverb_get_room_hf_level(reverb_ctxt);
+        reverb_settings->decayTime = reverb_get_decay_time(reverb_ctxt);
+        reverb_settings->decayHFRatio = reverb_get_decay_hf_ratio(reverb_ctxt);
+        reverb_settings->reverbLevel = reverb_get_reverb_level(reverb_ctxt);
+        reverb_settings->reverbDelay = reverb_get_reverb_delay(reverb_ctxt);
+        reverb_settings->reflectionsLevel = reverb_get_reflections_level(reverb_ctxt);
+        reverb_settings->reflectionsDelay = reverb_get_reflections_delay(reverb_ctxt);
+        reverb_settings->diffusion = reverb_get_diffusion(reverb_ctxt);
+        reverb_settings->density = reverb_get_density(reverb_ctxt);
         break;
     default:
         p->status = -EINVAL;
@@ -496,6 +593,7 @@
     int16_t level;
     int16_t ratio;
     uint32_t time;
+    uint32_t delay;
 
     ALOGV("%s: ctxt %p, param %d", __func__, reverb_ctxt, param);
 
@@ -515,6 +613,7 @@
     switch (param) {
     case REVERB_PARAM_PROPERTIES:
         reverb_settings = (reverb_settings_t *)value;
+        reverb_set_all_properties(reverb_ctxt, reverb_settings);
         break;
     case REVERB_PARAM_ROOM_LEVEL:
         level = *(int16_t *)value;
@@ -536,6 +635,18 @@
         level = *(int16_t *)value;
         reverb_set_reverb_level(reverb_ctxt, level);
         break;
+    case REVERB_PARAM_REVERB_DELAY:
+        delay = *(uint32_t *)value;
+        reverb_set_reverb_delay(reverb_ctxt, delay);
+        break;
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+        level = *(int16_t *)value;
+        reverb_set_reflections_level(reverb_ctxt, level);
+        break;
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+        delay = *(uint32_t *)value;
+        reverb_set_reflections_delay(reverb_ctxt, delay);
+        break;
     case REVERB_PARAM_DIFFUSION:
         ratio = *(int16_t *)value;
         reverb_set_diffusion(reverb_ctxt, ratio);
@@ -544,10 +655,6 @@
         ratio = *(int16_t *)value;
         reverb_set_density(reverb_ctxt, ratio);
         break;
-    case REVERB_PARAM_REFLECTIONS_LEVEL:
-    case REVERB_PARAM_REFLECTIONS_DELAY:
-    case REVERB_PARAM_REVERB_DELAY:
-        break;
     default:
         p->status = -EINVAL;
         break;
diff --git a/post_proc/reverb.h b/post_proc/reverb.h
index 1a5ca0d..3bdd9af 100644
--- a/post_proc/reverb.h
+++ b/post_proc/reverb.h
@@ -40,7 +40,7 @@
     uint32_t    reverbDelay;
     int16_t     diffusion;
     int16_t     density;
-} reverb_settings_t;
+}  __attribute__((packed)) reverb_settings_t;
 
 typedef struct reverb_context_s {
     effect_context_t common;
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
new file mode 100644
index 0000000..e1dd026
--- /dev/null
+++ b/post_proc/volume_listener.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (c) 2015, 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
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "volume_listener"
+//#define LOG_NDEBUG 0
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#include <cutils/list.h>
+#include <cutils/log.h>
+#include <hardware/audio_effect.h>
+#include <cutils/properties.h>
+
+#define PRIMARY_HAL_PATH XSTR(LIB_AUDIO_HAL)
+#define XSTR(x) STR(x)
+#define STR(x) #x
+
+#define VOL_FLAG ( EFFECT_FLAG_TYPE_INSERT | \
+                   EFFECT_FLAG_VOLUME_IND | \
+                   EFFECT_FLAG_DEVICE_IND | \
+                   EFFECT_FLAG_OFFLOAD_SUPPORTED)
+
+#define PRINT_STREAM_TYPE(i) ALOGV("descriptor found and is of stream type %s ",\
+                                                            i == MUSIC?"MUSIC": \
+                                                            i == RING?"RING": \
+                                                            i == ALARM?"ALARM": \
+                                                            i == VOICE_CALL?"Voice_call": \
+                                                            i == NOTIFICATION?"Notification":\
+                                                            "--INVALID--"); \
+
+#define MAX_GAIN_LEVELS 5
+
+#define AHAL_GAIN_DEPENDENT_INTERFACE_FUNCTION "audio_hw_send_gain_dep_calibration"
+
+enum {
+    VOL_LISTENER_STATE_UNINITIALIZED,
+    VOL_LISTENER_STATE_INITIALIZED,
+    VOL_LISTENER_STATE_ACTIVE,
+};
+
+typedef struct vol_listener_context_s vol_listener_context_t;
+static const struct effect_interface_s effect_interface;
+
+/* flag to avoid multiple initialization */
+static bool initialized = false;
+
+/* current gain dep cal level that was pushed succesfully */
+static int current_gain_dep_cal_level = -1;
+
+enum STREAM_TYPE {
+    MUSIC,
+    RING,
+    ALARM,
+    VOICE_CALL,
+    NOTIFICATION,
+    MAX_STREAM_TYPES,
+};
+
+struct vol_listener_context_s {
+    const struct effect_interface_s *itfe;
+    struct listnode effect_list_node;
+    effect_config_t config;
+    const effect_descriptor_t *desc;
+    uint32_t stream_type;
+    uint32_t session_id;
+    uint32_t state;
+    uint32_t dev_id;
+    float left_vol;
+    float right_vol;
+};
+
+/* volume listener, music UUID: 08b8b058-0590-11e5-ac71-0025b32654a0 */
+const effect_descriptor_t vol_listener_music_descriptor = {
+    { 0x08b8b058, 0x0590, 0x11e5, 0xac71, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } },  // type
+    { 0x08b8b058, 0x0590, 0x11e5, 0xac71, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } },  // uuid
+    EFFECT_CONTROL_API_VERSION,
+    VOL_FLAG,
+    0, /* TODO */
+    1,
+    "Volume listener for Music",
+    "Qualcomm Technologies Inc.",
+};
+
+/* volume listener, ring UUID: 0956df94-0590-11e5-bdbe-0025b32654a0 */
+const effect_descriptor_t vol_listener_ring_descriptor = {
+    { 0x0956df94, 0x0590, 0x11e5, 0xbdbe, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // type
+    { 0x0956df94, 0x0590, 0x11e5, 0xbdbe, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // uuid
+    EFFECT_CONTROL_API_VERSION,
+    VOL_FLAG,
+    0, /* TODO */
+    1,
+    "Volume listener for ring",
+    "Qualcomm Technologies Inc",
+};
+
+/* volume listener, alarm UUID: 09f303e2-0590-11e5-8fdb-0025b32654a0 */
+const effect_descriptor_t vol_listener_alarm_descriptor = {
+    { 0x09f303e2, 0x0590, 0x11e5, 0x8fdb, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // type
+    { 0x09f303e2, 0x0590, 0x11e5, 0x8fdb, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // uuid
+    EFFECT_CONTROL_API_VERSION,
+    VOL_FLAG,
+    0, /* TODO */
+    1,
+    "Volume listener for alarm",
+    "Qualcomm Technologies Inc",
+};
+
+/* volume listener, voice call UUID: 0ace5c08-0590-11e5-ae9e-0025b32654a0 */
+const effect_descriptor_t vol_listener_voice_call_descriptor = {
+    { 0x0ace5c08, 0x0590, 0x11e5, 0xae9e, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // type
+    { 0x0ace5c08, 0x0590, 0x11e5, 0xae9e, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // uuid
+    EFFECT_CONTROL_API_VERSION,
+    VOL_FLAG,
+    0, /* TODO */
+    1,
+    "Volume listener for voice call",
+    "Qualcomm Technologies Inc",
+};
+
+/* volume listener, notification UUID: 0b776dde-0590-11e5-81ba-0025b32654a0 */
+const effect_descriptor_t vol_listener_notification_descriptor = {
+    { 0x0b776dde, 0x0590, 0x11e5, 0x81ba, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // type
+    { 0x0b776dde, 0x0590, 0x11e5, 0x81ba, { 0x00, 0x25, 0xb3, 0x26, 0x54, 0xa0 } }, // uuid
+    EFFECT_CONTROL_API_VERSION,
+    VOL_FLAG,
+    0, /* TODO */
+    1,
+    "Volume listener for notification",
+    "Qualcomm Technologies Inc",
+};
+
+struct amp_db_and_gain_table {
+    float amp;
+    float db;
+    uint32_t level;
+} amp_to_dBLevel_table;
+
+// using gain level for non-drc volume curve
+static const struct amp_db_and_gain_table  volume_curve_gain_mapping_table[MAX_GAIN_LEVELS] = {
+    /* Level 0 in the calibration database contains default calibration */
+    { 0.001774, -55, 5 },
+    { 0.501187,  -6, 4 },
+    { 0.630957,  -4, 3 },
+    { 0.794328,  -2, 2 },
+    { 1.0,        0, 1 },
+};
+
+static const effect_descriptor_t *descriptors[] = {
+    &vol_listener_music_descriptor,
+    &vol_listener_ring_descriptor,
+    &vol_listener_alarm_descriptor,
+    &vol_listener_voice_call_descriptor,
+    &vol_listener_notification_descriptor,
+    NULL,
+};
+
+pthread_once_t once = PTHREAD_ONCE_INIT;
+/* flag to indicate if init was success */
+static int init_status;
+
+/* current volume level for which gain dep cal level was selected */
+static float current_vol = 0.0;
+
+/* HAL interface to send calibration */
+static bool (*send_gain_dep_cal)(int);
+
+/* if dumping allowed */
+static bool dumping_enabled = false;
+
+/* list of created effects. */
+struct listnode vol_effect_list;
+
+/* lock must be held when modifying or accessing created_effects_list */
+pthread_mutex_t vol_listner_init_lock;
+
+/*
+ *  Local functions
+ */
+static void dump_list_l()
+{
+    struct listnode *node;
+    vol_listener_context_t *context;
+
+    ALOGW("DUMP_START :: ===========");
+
+    list_for_each(node, &vol_effect_list) {
+        context = node_to_item(node, struct vol_listener_context_s, effect_list_node);
+        // dump stream_type / Device / session_id / left / righ volume
+        ALOGW("%s: streamType [%s] Device [%d] state [%d] sessionID [%d] volume (L/R) [%f / %f] ",
+        __func__,
+        context->stream_type == MUSIC ? "MUSIC" :
+        context->stream_type == RING ? "RING" :
+        context->stream_type == ALARM ? "ALARM" :
+        context->stream_type == VOICE_CALL ? "VOICE_CALL" :
+        context->stream_type == NOTIFICATION ? "NOTIFICATION" : "--INVALID--",
+        context->dev_id, context->state, context->session_id, context->left_vol,context->right_vol);
+    }
+
+    ALOGW("DUMP_END :: ===========");
+}
+
+static void check_and_set_gain_dep_cal()
+{
+    // iterate through list and make decision to set new gain dep cal level for speaker device
+    // 1. find all usecase active on speaker
+    // 2. find average of left and right for each usecase
+    // 3. find the highest of all the active usecase
+    // 4. if new value is different than the current value then load new calibration
+
+    struct listnode *node = NULL;
+    float new_vol = 0.0;
+    int max_level = 0;
+    vol_listener_context_t *context = NULL;
+    if (dumping_enabled) {
+        dump_list_l();
+    }
+
+    ALOGV("%s ==> Start ...", __func__);
+
+    // select the highest volume on speaker device
+    list_for_each(node, &vol_effect_list) {
+        context = node_to_item(node, struct vol_listener_context_s, effect_list_node);
+        if ((context->state == VOL_LISTENER_STATE_ACTIVE) &&
+            (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) &&
+            (new_vol < (context->left_vol + context->right_vol) / 2)) {
+            new_vol = (context->left_vol + context->right_vol) / 2;
+        }
+    }
+
+    if (new_vol != current_vol) {
+        ALOGV("%s:: Change in decision :: current volume is %f new volume is %f",
+              __func__, current_vol, new_vol);
+
+        if (send_gain_dep_cal != NULL) {
+            // send Gain dep cal level
+            int gain_dep_cal_level = -1;
+
+            if (new_vol >= 1) { // max amplitude, use highest DRC level
+                gain_dep_cal_level = volume_curve_gain_mapping_table[MAX_GAIN_LEVELS - 1].level;
+            } else if (new_vol <= 0) {
+                gain_dep_cal_level = volume_curve_gain_mapping_table[0].level;
+            } else {
+                for (max_level = 0; max_level + 1 < MAX_GAIN_LEVELS; max_level++) {
+                    if (new_vol < volume_curve_gain_mapping_table[max_level + 1].amp &&
+                        new_vol >= volume_curve_gain_mapping_table[max_level].amp) {
+                        gain_dep_cal_level = volume_curve_gain_mapping_table[max_level].level;
+                        ALOGV("%s: volume(%f), gain dep cal selcetd %d ",
+                              __func__, current_vol, gain_dep_cal_level);
+                        break;
+                    }
+                }
+            }
+
+            // check here if previous gain dep cal level was not same
+            if (gain_dep_cal_level != -1) {
+                if (gain_dep_cal_level != current_gain_dep_cal_level) {
+                    // decision made .. send new level now
+                    if (!send_gain_dep_cal(gain_dep_cal_level)) {
+                        ALOGE("%s: Failed to set gain dep cal level", __func__);
+                    } else {
+                        // Success in setting the gain dep cal level, store new level and Volume
+                        if (dumping_enabled) {
+                            ALOGW("%s: (old/new) Volume (%f/%f) (old/new) level (%d/%d)",
+                                  __func__, current_vol, new_vol, current_gain_dep_cal_level,
+                                  gain_dep_cal_level);
+                        } else {
+                            ALOGV("%s: Change in Cal::(old/new) Volume (%f/%f) (old/new) level (%d/%d)",
+                                  __func__, current_vol, new_vol, current_gain_dep_cal_level,
+                                  gain_dep_cal_level);
+                        }
+                        current_gain_dep_cal_level = gain_dep_cal_level;
+                        current_vol = new_vol;
+                    }
+                } else {
+                    if (dumping_enabled) {
+                        ALOGW("%s: volume changed but gain dep cal level is still the same",
+                              __func__);
+                    } else {
+                        ALOGV("%s: volume changed but gain dep cal level is still the same",
+                              __func__);
+                    }
+                }
+            } else {
+                ALOGW("%s: Failed to find gain dep cal level for volume %f", __func__, new_vol);
+            }
+        } else {
+            ALOGE("%s: not able to send calibration, NULL function pointer",
+                  __func__);
+        }
+    } else {
+        ALOGV("%s:: volume not changed, stick to same config ..... ", __func__);
+    }
+
+    ALOGV("check_and_set_gain_dep_cal ==> End ");
+}
+
+/*
+ * Effect Control Interface Implementation
+ */
+
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
+static int vol_effect_process(effect_handle_t self,
+                              audio_buffer_t *in_buffer,
+                              audio_buffer_t *out_buffer)
+{
+    int status = 0;
+    ALOGV("%s Called ", __func__);
+
+    vol_listener_context_t *context = (vol_listener_context_t *)self;
+    pthread_mutex_lock(&vol_listner_init_lock);
+
+    if (context->state != VOL_LISTENER_STATE_ACTIVE) {
+        ALOGE("%s: state is not active .. return error", __func__);
+        status = -EINVAL;
+        goto exit;
+    }
+
+    // calculation based on channel count 2
+    if (in_buffer->raw != out_buffer->raw) {
+        if (context->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            size_t i;
+            for (i = 0; i < out_buffer->frameCount*2; i++) {
+                out_buffer->s16[i] = clamp16(out_buffer->s16[i] + in_buffer->s16[i]);
+            }
+        } else {
+            memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
+        }
+    } else {
+        ALOGV("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
+              __func__);
+    }
+
+exit:
+    pthread_mutex_unlock(&vol_listner_init_lock);
+    return status;
+}
+
+
+static int vol_effect_command(effect_handle_t self,
+                              uint32_t cmd_code, uint32_t cmd_size,
+                              void *p_cmd_data, uint32_t *reply_size,
+                              void *p_reply_data)
+{
+    vol_listener_context_t *context = (vol_listener_context_t *)self;
+    int status = 0;
+
+    ALOGV("%s Called ", __func__);
+    pthread_mutex_lock(&vol_listner_init_lock);
+
+    if (context == NULL || context->state == VOL_LISTENER_STATE_UNINITIALIZED) {
+        ALOGE("%s: %s is NULL", __func__, (context == NULL) ?
+              "context" : "context->state");
+        status = -EINVAL;
+        goto exit;
+    }
+
+    switch (cmd_code) {
+    case EFFECT_CMD_INIT:
+        ALOGV("%s :: cmd called EFFECT_CMD_INIT", __func__);
+        if (p_reply_data == NULL || *reply_size != sizeof(int)) {
+            ALOGE("%s: EFFECT_CMD_INIT: %s, sending -EINVAL", __func__,
+                  (p_reply_data == NULL) ? "p_reply_data is NULL" :
+                  "*reply_size != sizeof(int)");
+            return -EINVAL;
+        }
+        *(int *)p_reply_data = 0;
+        break;
+
+    case EFFECT_CMD_SET_CONFIG:
+        ALOGV("%s :: cmd called EFFECT_CMD_SET_CONFIG", __func__);
+        if (p_cmd_data == NULL || cmd_size != sizeof(effect_config_t)
+                || p_reply_data == NULL || reply_size == NULL || *reply_size != sizeof(int)) {
+            return -EINVAL;
+        }
+        context->config = *(effect_config_t *)p_cmd_data;
+        *(int *)p_reply_data = 0;
+        break;
+
+    case EFFECT_CMD_GET_CONFIG:
+        ALOGV("%s :: cmd called EFFECT_CMD_GET_CONFIG", __func__);
+        break;
+
+    case EFFECT_CMD_RESET:
+        ALOGV("%s :: cmd called EFFECT_CMD_RESET", __func__);
+        break;
+
+    case EFFECT_CMD_SET_AUDIO_MODE:
+        ALOGV("%s :: cmd called EFFECT_CMD_SET_AUDIO_MODE", __func__);
+        break;
+
+    case EFFECT_CMD_OFFLOAD:
+        ALOGV("%s :: cmd called EFFECT_CMD_OFFLOAD", __func__);
+        if (p_reply_data == NULL || *reply_size != sizeof(int)) {
+            ALOGE("%s: EFFECT_CMD_OFFLOAD: %s, sending -EINVAL", __func__,
+                  (p_reply_data == NULL) ? "p_reply_data is NULL" :
+                  "*reply_size != sizeof(int)");
+            return -EINVAL;
+        }
+        *(int *)p_reply_data = 0;
+        break;
+
+    case EFFECT_CMD_ENABLE:
+        ALOGV("%s :: cmd called EFFECT_CMD_ENABLE", __func__);
+        if (p_reply_data == NULL || *reply_size != sizeof(int)) {
+            ALOGE("%s: EFFECT_CMD_ENABLE: %s, sending -EINVAL", __func__,
+                   (p_reply_data == NULL) ? "p_reply_data is NULL" :
+                   "*reply_size != sizeof(int)");
+            status = -EINVAL;
+            goto exit;
+        }
+
+        if (context->state != VOL_LISTENER_STATE_INITIALIZED) {
+            ALOGE("%s: EFFECT_CMD_ENABLE : state not INITIALIZED", __func__);
+            status = -ENOSYS;
+            goto exit;
+        }
+
+        context->state = VOL_LISTENER_STATE_ACTIVE;
+        *(int *)p_reply_data = 0;
+
+        // After changing the state and if device is speaker
+        // recalculate gain dep cal level
+        if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+                check_and_set_gain_dep_cal();
+        }
+
+        break;
+
+    case EFFECT_CMD_DISABLE:
+        ALOGV("%s :: cmd called EFFECT_CMD_DISABLE", __func__);
+        if (p_reply_data == NULL || *reply_size != sizeof(int)) {
+            ALOGE("%s: EFFECT_CMD_DISABLE: %s, sending -EINVAL", __func__,
+                  (p_reply_data == NULL) ? "p_reply_data is NULL" :
+                  "*reply_size != sizeof(int)");
+            status = -EINVAL;
+            goto exit;
+        }
+
+        if (context->state != VOL_LISTENER_STATE_ACTIVE) {
+            ALOGE("%s: EFFECT_CMD_ENABLE : state not ACTIVE", __func__);
+            status = -ENOSYS;
+            goto exit;
+        }
+
+        context->state = VOL_LISTENER_STATE_INITIALIZED;
+        *(int *)p_reply_data = 0;
+
+        // After changing the state and if device is speaker
+        // recalculate gain dep cal level
+        if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+            check_and_set_gain_dep_cal();
+        }
+
+        break;
+
+    case EFFECT_CMD_GET_PARAM:
+        ALOGV("%s :: cmd called EFFECT_CMD_GET_PARAM", __func__);
+        break;
+
+    case EFFECT_CMD_SET_PARAM:
+        ALOGV("%s :: cmd called EFFECT_CMD_SET_PARAM", __func__);
+        break;
+
+    case EFFECT_CMD_SET_DEVICE:
+        {
+            uint32_t new_device;
+            bool recompute_gain_dep_cal_Level = false;
+            ALOGV("cmd called EFFECT_CMD_SET_DEVICE ");
+
+            if (p_cmd_data == NULL) {
+                ALOGE("%s: EFFECT_CMD_SET_DEVICE: cmd data NULL", __func__);
+                status = -EINVAL;
+                goto exit;
+            }
+
+            new_device = *(uint32_t *)p_cmd_data;
+            ALOGV("%s :: EFFECT_CMD_SET_DEVICE: (current/new) device (0x%x / 0x%x)",
+                   __func__, context->dev_id, new_device);
+
+            // check if old or new device is speaker
+            if ((context->dev_id ==  AUDIO_DEVICE_OUT_SPEAKER) ||
+                (new_device == AUDIO_DEVICE_OUT_SPEAKER)) {
+                recompute_gain_dep_cal_Level = true;
+            }
+
+            context->dev_id = new_device;
+
+            if (recompute_gain_dep_cal_Level) {
+                check_and_set_gain_dep_cal();
+            }
+        }
+        break;
+
+    case EFFECT_CMD_SET_VOLUME:
+        {
+            float left_vol = 0, right_vol = 0;
+            bool recompute_gain_dep_cal_Level = false;
+
+            ALOGV("cmd called EFFECT_CMD_SET_VOLUME");
+            if (p_cmd_data == NULL || cmd_size != 2 * sizeof(uint32_t)) {
+                ALOGE("%s: EFFECT_CMD_SET_VOLUME: %s", __func__, (p_cmd_data == NULL) ?
+                      "p_cmd_data is NULL" : "cmd_size issue");
+                status = -EINVAL;
+                goto exit;
+            }
+
+            if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+                recompute_gain_dep_cal_Level = true;
+            }
+
+            left_vol = (float)(*(uint32_t *)p_cmd_data) / (1 << 24);
+            right_vol = (float)(*((uint32_t *)p_cmd_data + 1)) / (1 << 24);
+            ALOGV("Current Volume (%f / %f ) new Volume (%f / %f)", context->left_vol,
+                  context->right_vol, left_vol, right_vol);
+
+            context->left_vol = left_vol;
+            context->right_vol = right_vol;
+
+            // recompute gan dep cal level only if volume changed on speaker device
+            if (recompute_gain_dep_cal_Level) {
+                check_and_set_gain_dep_cal();
+            }
+        }
+        break;
+
+    default:
+        ALOGW("volume_listener_command invalid command %d", cmd_code);
+        status = -ENOSYS;
+        break;
+    }
+
+exit:
+    pthread_mutex_unlock(&vol_listner_init_lock);
+    return status;
+}
+
+/* Effect Control Interface Implementation: get_descriptor */
+static int vol_effect_get_descriptor(effect_handle_t   self,
+                                     effect_descriptor_t *descriptor)
+{
+    vol_listener_context_t *context = (vol_listener_context_t *)self;
+    ALOGV("%s Called ", __func__);
+
+    if (descriptor == NULL) {
+        ALOGE("%s: descriptor is NULL", __func__);
+        return -EINVAL;
+    }
+
+    *descriptor = *context->desc;
+    return 0;
+}
+
+static void init_once()
+{
+    int i = 0;
+    if (initialized) {
+        ALOGV("%s : already init .. do nothing", __func__);
+        return;
+    }
+
+    ALOGD("%s Called ", __func__);
+    pthread_mutex_init(&vol_listner_init_lock, NULL);
+
+    // get hal function pointer
+    if (access(PRIMARY_HAL_PATH, R_OK) == 0) {
+        void *hal_lib_pointer = dlopen(PRIMARY_HAL_PATH, RTLD_NOW);
+        if (hal_lib_pointer == NULL) {
+            ALOGE("%s: DLOPEN failed for %s", __func__, PRIMARY_HAL_PATH);
+            send_gain_dep_cal = NULL;
+        } else {
+            ALOGV("%s: DLOPEN of %s Succes .. next get HAL entry function", __func__, PRIMARY_HAL_PATH);
+            send_gain_dep_cal = (bool (*)(int))dlsym(hal_lib_pointer, AHAL_GAIN_DEPENDENT_INTERFACE_FUNCTION);
+            if (send_gain_dep_cal == NULL) {
+                ALOGE("Couldnt able to get the function symbol");
+            }
+        }
+    } else {
+        ALOGE("%s: not able to acces lib %s ", __func__, PRIMARY_HAL_PATH);
+        send_gain_dep_cal = NULL;
+    }
+
+    // check system property to see if dumping is required
+    char check_dump_val[PROPERTY_VALUE_MAX];
+    property_get("audio.volume.listener.dump", check_dump_val, "0");
+    if (atoi(check_dump_val)) {
+        dumping_enabled = true;
+    }
+
+    init_status = 0;
+    list_init(&vol_effect_list);
+    initialized = true;
+}
+
+static int lib_init()
+{
+    pthread_once(&once, init_once);
+    ALOGV("%s Called ", __func__);
+    return init_status;
+}
+
+static int vol_prc_lib_create(const effect_uuid_t *uuid,
+                              int32_t session_id,
+                              int32_t io_id __unused,
+                              effect_handle_t *p_handle)
+{
+    int itt = 0;
+    vol_listener_context_t *context = NULL;
+
+    ALOGV("volume_prc_lib_create .. called ..");
+
+    if (lib_init() != 0) {
+        return init_status;
+    }
+
+    if (p_handle == NULL || uuid == NULL) {
+        ALOGE("%s: %s is NULL", __func__, (p_handle == NULL) ? "p_handle" : "uuid");
+        return -EINVAL;
+    }
+
+    context = (vol_listener_context_t *)calloc(1, sizeof(vol_listener_context_t));
+
+    if (context == NULL) {
+        ALOGE("%s: failed to allocate for context .. oops !!", __func__);
+        return -EINVAL;
+    }
+
+    // check if UUID is supported
+    for (itt = 0; descriptors[itt] != NULL; itt++) {
+        if (memcmp(uuid, &descriptors[itt]->uuid, sizeof(effect_uuid_t)) == 0) {
+            // check if this correct .. very imp
+            context->desc = descriptors[itt];
+            context->stream_type = itt;
+            PRINT_STREAM_TYPE(itt)
+            break;
+        }
+    }
+
+    if (descriptors[itt] == NULL) {
+        ALOGE("%s .. couldnt find passed uuid, something wrong", __func__);
+        free(context);
+        return -EINVAL;
+    }
+
+    ALOGV("%s CREATED_CONTEXT %p", __func__, context);
+
+    context->itfe = &effect_interface;
+    context->state = VOL_LISTENER_STATE_INITIALIZED;
+    context->dev_id = AUDIO_DEVICE_NONE;
+    context->session_id = session_id;
+
+    // Add this to master list
+    pthread_mutex_lock(&vol_listner_init_lock);
+    list_add_tail(&vol_effect_list, &context->effect_list_node);
+    if (dumping_enabled) {
+        dump_list_l();
+    }
+    pthread_mutex_unlock(&vol_listner_init_lock);
+
+    *p_handle = (effect_handle_t)context;
+    return 0;
+}
+
+static int vol_prc_lib_release(effect_handle_t handle)
+{
+    struct listnode *node = NULL;
+    vol_listener_context_t *context = NULL;
+    vol_listener_context_t *recv_contex = (vol_listener_context_t *)handle;
+    int status = -1;
+    bool recompute_flag = false;
+    int active_stream_count = 0;
+    ALOGV("%s context %p", __func__, handle);
+    if (recv_contex == NULL || recv_contex->desc == NULL) {
+        ALOGE("%s: Got invalid handle while release, DO NOTHING ", __func__);
+        return status;
+    }
+
+    pthread_mutex_lock(&vol_listner_init_lock);
+
+    // check if the handle/context provided is valid
+    list_for_each(node, &vol_effect_list) {
+        context = node_to_item(node, struct vol_listener_context_s, effect_list_node);
+        if ((memcmp(&(context->desc->uuid), &(recv_contex->desc->uuid), sizeof(effect_uuid_t)) == 0)
+            && (context->session_id == recv_contex->session_id)
+            && (context->stream_type == recv_contex->stream_type)) {
+            ALOGV("--- Found something to remove ---");
+            PRINT_STREAM_TYPE(context->stream_type);
+            if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
+                recompute_flag = true;
+            }
+            list_remove(&context->effect_list_node);
+            free(context);
+            status = 0;
+            break;
+        } else {
+            ++active_stream_count;
+        }
+    }
+
+    if (status != 0) {
+        ALOGE("something wrong ... <<<--- Found NOTHING to remove ... ???? --->>>>>");
+    }
+
+    // if there are no active streams, reset cal and volume level
+    if (active_stream_count == 0) {
+        current_gain_dep_cal_level = -1;
+        current_vol = 0.0;
+    }
+
+    if (recompute_flag) {
+        check_and_set_gain_dep_cal();
+    }
+
+    if (dumping_enabled) {
+        dump_list_l();
+    }
+    pthread_mutex_unlock(&vol_listner_init_lock);
+    return status;
+}
+
+static int vol_prc_lib_get_descriptor(const effect_uuid_t *uuid,
+                                      effect_descriptor_t *descriptor)
+{
+    int i = 0;
+    ALOGV("%s Called ", __func__);
+    if (lib_init() != 0) {
+        return init_status;
+    }
+
+    if (descriptor == NULL || uuid == NULL) {
+        ALOGE("%s: %s is NULL", __func__, (descriptor == NULL) ? "descriptor" : "uuid");
+        return -EINVAL;
+    }
+
+    for (i = 0; descriptors[i] != NULL; i++) {
+        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
+            *descriptor = *descriptors[i];
+            return 0;
+        }
+    }
+
+    ALOGE("%s: couldnt found uuid passed, oops", __func__);
+    return  -EINVAL;
+}
+
+
+/* effect_handle_t interface implementation for volume listener effect */
+static const struct effect_interface_s effect_interface = {
+    vol_effect_process,
+    vol_effect_command,
+    vol_effect_get_descriptor,
+    NULL,
+};
+
+__attribute__((visibility("default")))
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+    .tag = AUDIO_EFFECT_LIBRARY_TAG,
+    .version = EFFECT_LIBRARY_API_VERSION,
+    .name = "Volume Listener Effect Library",
+    .implementor = "Qualcomm Technologies Inc.",
+    .create_effect = vol_prc_lib_create,
+    .release_effect = vol_prc_lib_release,
+    .get_descriptor = vol_prc_lib_get_descriptor,
+};
diff --git a/voice_processing/voice_processing.c b/voice_processing/voice_processing.c
index bb9bf3b..1e1e123 100644
--- a/voice_processing/voice_processing.c
+++ b/voice_processing/voice_processing.c
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "voice_processing"
 /*#define LOG_NDEBUG 0*/
+#include <stdlib.h>
 #include <dlfcn.h>
 #include <stdlib.h>
 #include <cutils/log.h>