Merge "hal: Add sound card update API"
diff --git a/audiod/Android.mk b/audiod/Android.mk
index c382c9d..c89b3cd 100644
--- a/audiod/Android.mk
+++ b/audiod/Android.mk
@@ -1,7 +1,10 @@
 LOCAL_PATH:= $(call my-dir)
 
 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 \
@@ -13,8 +16,11 @@
 	libcutils \
 	libutils \
 	libbinder \
-	libmedia \
-	libstlport
+	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
 
diff --git a/audiod/AudioDaemon.cpp b/audiod/AudioDaemon.cpp
index b4857c4..6f38218 100644
--- a/audiod/AudioDaemon.cpp
+++ b/audiod/AudioDaemon.cpp
@@ -125,6 +125,7 @@
         struct dirent* in_file;
         int fd;
         String8 path;
+        String8 d_name;
 
         if ((dp = opendir(events_dir)) == NULL) {
             ALOGE("Cannot open switch directory to get list of audio events %s", events_dir);
@@ -148,8 +149,9 @@
             if (fd == -1) {
                 ALOGE("Open %s failed : %s", path.string(), strerror(errno));
             } else {
-                mAudioEvents.push_back(std::make_pair(in_file->d_name, fd));
-                mAudioEventsStatus.push_back(std::make_pair(in_file->d_name, 0));
+                d_name = in_file->d_name;
+                mAudioEvents.push_back(std::make_pair(d_name, fd));
+                mAudioEventsStatus.push_back(std::make_pair(d_name, 0));
                 ALOGD("event status mAudioEventsStatus= %s",
                           mAudioEventsStatus[0].first.string());
             }
diff --git a/hal/Android.mk b/hal/Android.mk
index e0149f9..315aab2 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -53,6 +53,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_EDID)),true)
+    LOCAL_CFLAGS += -DHDMI_EDID
     LOCAL_SRC_FILES += edid.c
 endif
 
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 7bbe2f8..8c893c6 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -46,6 +46,9 @@
 #define AUDIO_FORMAT_PCM_24_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_8_24_BIT)
 #define AUDIO_OFFLOAD_CODEC_FORMAT  "music_offload_codec_format"
 #define audio_is_offload_pcm(format) (0)
+#define OFFLOAD_USE_SMALL_BUFFER false
+#else
+#define OFFLOAD_USE_SMALL_BUFFER (info->use_small_bufs)
 #endif
 
 #ifndef AFE_PROXY_ENABLED
@@ -221,6 +224,7 @@
 #define audio_extn_sound_trigger_set_parameters(adev, parms)           (0)
 #define audio_extn_sound_trigger_check_and_get_session(in)             (0)
 #define audio_extn_sound_trigger_stop_lab(in)                          (0)
+#define audio_extn_sound_trigger_read(in, buffer, bytes)               (0)
 #else
 
 enum st_event_type {
@@ -241,6 +245,8 @@
                                              struct str_parms *parms);
 void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in);
 void audio_extn_sound_trigger_stop_lab(struct stream_in *in);
+int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
+                                  size_t bytes);
 #endif
 
 #ifndef AUXPCM_BT_ENABLED
@@ -316,6 +322,9 @@
 void audio_extn_dolby_set_dmid(struct audio_device *adev);
 #else
 #define audio_extn_dolby_set_dmid(adev)                 (0)
+#define AUDIO_CHANNEL_OUT_PENTA (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER)
+#define AUDIO_CHANNEL_OUT_SURROUND (AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | \
+                                    AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_BACK_CENTER)
 #endif
 
 
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 9051334..3c16c88 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -30,6 +30,7 @@
 /* #define LOG_NDEBUG 0 */
 #define LOG_NDDEBUG 0
 
+#include <errno.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <dlfcn.h>
@@ -64,7 +65,7 @@
 {
     struct sound_trigger_info  *st_ses_info = NULL;
     struct listnode *node;
-    ALOGD("%s: list %d capture_handle %d", __func__,
+    ALOGV("%s: list empty %d capture_handle %d", __func__,
            list_empty(&st_dev->st_ses_list), capture_handle);
     list_for_each(node, &st_dev->st_ses_list) {
         st_ses_info = node_to_item(node, struct sound_trigger_info , list);
@@ -128,6 +129,45 @@
     return status;
 }
 
+int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
+                       size_t bytes)
+{
+    int ret = -1;
+    struct sound_trigger_info  *st_info = NULL;
+    audio_event_info_t event;
+
+    if (!st_dev)
+       return ret;
+
+    if (!in->is_st_session_active) {
+        ALOGE(" %s: Sound trigger is not active", __func__);
+        goto exit;
+    }
+    if(in->standby)
+        in->standby = false;
+
+    pthread_mutex_lock(&st_dev->lock);
+    st_info = get_sound_trigger_info(in->capture_handle);
+    pthread_mutex_unlock(&st_dev->lock);
+    if (st_info) {
+        event.u.aud_info.ses_info = &st_info->st_ses;
+        event.u.aud_info.buf = buffer;
+        event.u.aud_info.num_bytes = bytes;
+        ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event);
+    }
+
+exit:
+    if (ret) {
+        if (-ENETRESET == ret)
+            in->is_st_session_active = false;
+        memset(buffer, 0, bytes);
+        ALOGV("%s: read failed status %d - sleep", __func__, ret);
+        usleep((bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) *
+                                   in->config.rate));
+    }
+    return ret;
+}
+
 void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
 {
     int status = 0;
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 5ea5a43..e703b13 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -485,6 +485,7 @@
     enable_audio_route(adev, uc_info_tx);
 
     pcm_dev_tx_id = platform_get_pcm_device_id(uc_info_tx->id, PCM_CAPTURE);
+    ALOGV("%s: pcm device id %d", __func__, pcm_dev_tx_id);
     if (pcm_dev_tx_id < 0) {
         ALOGE("%s: Invalid pcm device for usecase (%d)",
               __func__, uc_info_tx->id);
@@ -647,6 +648,7 @@
     char wsa_path[MAX_PATH] = {0};
     int spk_1_tzn, spk_2_tzn;
     char buf[32] = {0};
+    int ret;
 
     /* If the value of this persist.spkr.cal.duration is 0
      * then it means it will take 30min to calibrate
@@ -756,13 +758,17 @@
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
                        for (i = 0; i < NUM_ATTEMPTS; i++) {
-                            if (read(thermal_fd, buf, sizeof(buf))) {
+                            if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
                                 t0_spk_1 = atoi(buf);
-                                if (i > 0 && (t0_spk_1 != t0_spk_prior))
+                                if (i > 0 && (t0_spk_1 != t0_spk_prior)) {
+                                    ALOGE("%s: spkr1 curr temp: %d, prev temp: %d\n",
+                                          __func__, t0_spk_1, t0_spk_prior);
                                     break;
+                                }
                                 t0_spk_prior = t0_spk_1;
+                                sleep(1);
                             } else {
-                               ALOGE("%s: read fail for %s\n", __func__, wsa_path);
+                               ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
                                break;
                             }
                         }
@@ -773,26 +779,30 @@
                    if (i == NUM_ATTEMPTS) {
                        /*Convert temp into q6 format*/
                        t0_spk_1 = (t0_spk_1 * (1 << 6));
-                       ALOGE("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
+                       ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
                    } else {
-                       ALOGE("%s: thermal equilibrium failed for spkr1 in %d readings\n",
-                                                __func__, NUM_ATTEMPTS);
+                       ALOGD("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
+                                                __func__, i, NUM_ATTEMPTS);
                        t0_spk_1 = SAFE_SPKR_TEMP_Q6;
                    }
                }
                if (spk_2_tzn >= 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
-                   ALOGE("%s: wsa_path: %s\n", __func__, wsa_path);
+                   ALOGD("%s: wsa_path: %s\n", __func__, wsa_path);
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
                        for (i = 0; i < NUM_ATTEMPTS; i++) {
-                            if (read(thermal_fd, buf, sizeof(buf))) {
+                            if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
                                 t0_spk_2 = atoi(buf);
-                                if (i > 0 && (t0_spk_2 != t0_spk_prior))
+                                if (i > 0 && (t0_spk_2 != t0_spk_prior)) {
+                                    ALOGE("%s: spkr2 curr temp: %d, prev temp: %d\n",
+                                          __func__, t0_spk_2, t0_spk_prior);
                                     break;
+                                }
                                 t0_spk_prior = t0_spk_2;
+                                sleep(1);
                             } else {
-                               ALOGE("%s: read fail for %s\n", __func__, wsa_path);
+                               ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
                                break;
                             }
                         }
@@ -803,10 +813,10 @@
                    if (i == NUM_ATTEMPTS) {
                        /*Convert temp into q6 format*/
                        t0_spk_2 = (t0_spk_2 * (1 << 6));
-                       ALOGE("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
+                       ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
                    } else {
-                       ALOGE("%s: thermal equilibrium failed for spkr2 in %d readings\n",
-                                                __func__, NUM_ATTEMPTS);
+                       ALOGE("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
+                                                __func__, i, NUM_ATTEMPTS);
                        t0_spk_2 = SAFE_SPKR_TEMP_Q6;
                    }
                }
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 3dbf159..7ad4811 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -71,7 +71,9 @@
 #ifdef COMPRESS_VOIP_ENABLED
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
 #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[] = {
@@ -566,8 +568,11 @@
     app_type_cfg[len++] = 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))
+        (out->format == AUDIO_FORMAT_E_AC3_JOC))
+#ifdef HDMI_PASSTHROUGH_ENABLED
+        && (out->flags  & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
+#endif
+        )
         app_type_cfg[len++] = sample_rate * 4;
     else
         app_type_cfg[len++] = sample_rate;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9110fa8..4bc6b59 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -252,6 +252,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) {
 
 
@@ -623,7 +643,7 @@
         ALOGV("%s: backend_idx: %d,"
               "usecase_backend_idx: %d, curr device: %s, usecase device:"
               "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
-            platform_get_snd_device_name(usecase->out_snd_device));
+        platform_get_snd_device_name(usecase->out_snd_device));
 
         if (usecase->type != PCM_CAPTURE &&
                 (usecase->out_snd_device != snd_device || force_routing)  &&
@@ -2185,7 +2205,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);
@@ -2606,31 +2626,29 @@
 
     pthread_mutex_lock(&in->lock);
 
-    if (in->pcm) {
-        if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
-            ALOGD(" %s: sound card is not active/SSR state", __func__);
-            ret= -EIO;;
-            goto exit;
-        } else {
-            if (in->is_st_session &&  !in->is_st_session_active) {
-                ALOGD(" %s: Sound trigger is not active/SSR", __func__);
-                ret= -EIO;;
-                goto exit;
-            }
-        }
+    if (in->is_st_session) {
+        ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
+        /* Read from sound trigger HAL */
+        audio_extn_sound_trigger_read(in, buffer, bytes);
+        pthread_mutex_unlock(&in->lock);
+        return bytes;
+    }
+
+    if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
+        ALOGD(" %s: sound card is not active/SSR state", __func__);
+        ret= -EIO;;
+        goto exit;
     }
 
     if (in->standby) {
-        if (!in->is_st_session) {
-            pthread_mutex_lock(&adev->lock);
-            if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
-                ret = voice_extn_compress_voip_start_input_stream(in);
-            else
-                ret = start_input_stream(in);
-            pthread_mutex_unlock(&adev->lock);
-            if (ret != 0) {
-                goto exit;
-            }
+        pthread_mutex_lock(&adev->lock);
+        if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
+            ret = voice_extn_compress_voip_start_input_stream(in);
+        else
+            ret = start_input_stream(in);
+        pthread_mutex_unlock(&adev->lock);
+        if (ret != 0) {
+            goto exit;
         }
         in->standby = 0;
     }
@@ -2660,17 +2678,9 @@
 exit:
     /* ToDo: There may be a corner case when SSR happens back to back during
        start/stop. Need to post different error to handle that. */
-    if (-ENETRESET == ret) {
-        /* CPE SSR results in kernel returning ENETRESET for sound trigger
-          session reading on LAB data. In this case do not set sound card state
-          offline, instead mark this sound trigger session inactive to avoid
-          further reading of LAB data from CPE driver. Marking the session
-          inactive handles both CPE and ADSP SSR for sound trigger session */
-        if (!in->is_st_session)
-            set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
-        else
-            in->is_st_session_active = false;
-    }
+    if (-ENETRESET == ret)
+        set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
+
     pthread_mutex_unlock(&in->lock);
 
     if (ret != 0) {
@@ -2924,7 +2934,7 @@
         if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
             out->non_blocking = 1;
 
-        if (config->offload_info.use_small_bufs) {
+        if (platform_use_small_buffer(&config->offload_info)) {
             //this flag is set from framework only if its for PCM formats
             //no need to check for PCM format again
             out->non_blocking = 0;
@@ -3385,7 +3395,7 @@
 }
 
 static int adev_open_input_stream(struct audio_hw_device *dev,
-                                  audio_io_handle_t handle __unused,
+                                  audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   struct audio_config *config,
                                   struct audio_stream_in **stream_in,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 67f5279..5e61d36 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>
diff --git a/hal/edid.h b/hal/edid.h
index ec83ec8..0d7fbe6 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -92,5 +92,9 @@
     int  channel_allocation;
 } edid_audio_info;
 
+#ifndef HDMI_EDID
+#define edid_get_sink_caps(info, edid_data) (0)
+#else
 bool edid_get_sink_caps(edid_audio_info* info, char *edid_data);
+#endif
 #endif /* EDID_H */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 8f31b29..3a8f314 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -133,7 +133,6 @@
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_ANC_CAL] = "anc_cal",
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
-        [WCD9XXX_MAD_CAL] = "mad_cal",
 };
 
 #define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
@@ -175,6 +174,20 @@
 typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
 typedef int (*acdb_send_common_top_t) (void);
 
+typedef struct codec_backend_cfg {
+    uint32_t sample_rate;
+    uint32_t bit_width;
+    char     *bitwidth_mixer_ctl;
+    char     *samplerate_mixer_ctl;
+} codec_backend_cfg_t;
+
+typedef struct {
+    bool platform_na_prop_enabled;
+    bool ui_na_prop_enabled;
+} native_audio_prop;
+
+static native_audio_prop na_props = {0, 0};
+
 struct platform_data {
     struct audio_device *adev;
     bool fluence_in_spkr_mode;
@@ -211,6 +224,7 @@
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
+    codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
 };
 
 static bool is_external_codec = false;
@@ -294,6 +308,7 @@
     [SND_DEVICE_OUT_SPEAKER_WSA] = "wsa-speaker",
     [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
     [SND_DEVICE_OUT_HEADPHONES] = "headphones",
+    [SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
     [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",
@@ -398,6 +413,7 @@
     [SND_DEVICE_OUT_SPEAKER_WSA] = 135,
     [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
     [SND_DEVICE_OUT_HEADPHONES] = 10,
+    [SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = 10,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 10,
@@ -504,6 +520,7 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_WSA)},
     {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_SPEAKER_AND_HEADPHONES)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2)},
@@ -1036,7 +1053,7 @@
         backend_table[dev] = NULL;
     }
     for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
-        backend_bit_width_table[dev] = 16;
+        backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     }
 
     // TBD - do these go to the platform-info.xml file.
@@ -1058,6 +1075,7 @@
     backend_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
     backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
     backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
+    backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
 }
 
 void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1121,8 +1139,6 @@
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
 
-        if (!strcmp(cal_name_info[type], "mad_cal"))
-            calib.acdb_id = SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID;
         calib.get_size = 1;
         ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
                                                                  &calib);
@@ -1221,8 +1237,6 @@
     const char *snd_card_name;
     char mixer_xml_path[100],ffspEnable[PROPERTY_VALUE_MAX];
     char *cvd_version = NULL;
-
-    my_data = calloc(1, sizeof(struct platform_data));
     if (!my_data) {
         ALOGE("failed to allocate platform data");
         return NULL;
@@ -1454,6 +1468,26 @@
     audio_extn_dev_arbi_init();
 
     my_data->edid_info = NULL;
+
+    /* initialize backend config */
+    for (idx = 0; idx < MAX_CODEC_BACKENDS; idx++) {
+        my_data->current_backend_cfg[idx].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        if (idx == HEADPHONE_44_1_BACKEND)
+            my_data->current_backend_cfg[idx].sample_rate = OUTPUT_SAMPLING_RATE_44100;
+        my_data->current_backend_cfg[idx].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+    }
+
+    my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+        strdup("SLIM_0_RX Format");
+    my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+        strdup("SLIM_0_RX SampleRate");
+
+    my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].bitwidth_mixer_ctl =
+        strdup("SLIM_5_RX Format");
+    my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].samplerate_mixer_ctl =
+        strdup("SLIM_5_RX SampleRate");
+
+    my_data->edid_info = NULL;
     return my_data;
 }
 
@@ -1731,14 +1765,107 @@
     return backend_bit_width_table[snd_device];
 }
 
-int platform_set_native_support(bool codec_support __unused)
+int platform_set_native_support(bool codec_support)
 {
+    na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled
+        = codec_support;
+    ALOGV("%s: na_props.platform_na_prop_enabled: %d", __func__,
+           na_props.platform_na_prop_enabled);
     return 0;
 }
 
-int platform_get_backend_index(snd_device_t snd_device __unused)
+int platform_get_native_support()
 {
-    return 0;
+    int ret;
+    if (na_props.platform_na_prop_enabled) {
+        ret = na_props.ui_na_prop_enabled;
+    } else {
+        ret = na_props.platform_na_prop_enabled;
+    }
+    ALOGV("%s: na_props.ui_na_prop_enabled: %d", __func__,
+           na_props.ui_na_prop_enabled);
+    return ret;
+}
+
+void native_audio_get_params(struct str_parms *query,
+                             struct str_parms *reply,
+                             char *value, int len)
+{
+    int ret;
+    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_NATIVE_AUDIO,
+                            value, len);
+    if (ret >= 0) {
+        if (na_props.platform_na_prop_enabled) {
+            str_parms_add_str(reply, AUDIO_PARAMETER_KEY_NATIVE_AUDIO,
+                          na_props.ui_na_prop_enabled ? "true" : "false");
+            ALOGV("%s: na_props.ui_na_prop_enabled: %d", __func__,
+                   na_props.ui_na_prop_enabled);
+        } else {
+            str_parms_add_str(reply, AUDIO_PARAMETER_KEY_NATIVE_AUDIO,
+                              "false");
+            ALOGV("%s: native audio not supported: %d", __func__,
+                   na_props.platform_na_prop_enabled);
+        }
+    }
+}
+
+int native_audio_set_params(struct platform_data *platform,
+                            struct str_parms *parms, char *value, int len)
+{
+    int ret = 0;
+    struct audio_usecase *usecase;
+    struct listnode *node;
+
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO,
+                             value, len);
+    if (ret >= 0) {
+        if (na_props.platform_na_prop_enabled) {
+            if (!strncmp("true", value, sizeof("true")))
+                na_props.ui_na_prop_enabled = true;
+            else
+                na_props.ui_na_prop_enabled = false;
+
+            str_parms_del(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO);
+
+            /* Iterate through the usecase list and trigger device switch for
+            all the appropriate usecases */
+            list_for_each(node, &(platform->adev)->usecase_list) {
+                 usecase = node_to_item(node, struct audio_usecase, list);
+
+                 if (is_offload_usecase(usecase->id) &&
+                    (usecase->stream.out->devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+                    usecase->stream.out->devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) &&
+                    OUTPUT_SAMPLING_RATE_44100 == usecase->stream.out->sample_rate) {
+                         select_devices(platform->adev, usecase->id);
+                         ALOGV("%s: triggering dynamic device switch for usecase: "
+                               "%d, device: %d", __func__, usecase->id,
+                               usecase->stream.out->devices);
+                 }
+            }
+        } else {
+              ALOGV("%s: native audio not supported: %d", __func__,
+                     na_props.platform_na_prop_enabled);
+        }
+    }
+    return ret;
+}
+
+int platform_get_backend_index(snd_device_t snd_device)
+{
+    int32_t port = DEFAULT_CODEC_BACKEND;
+
+    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
+        if (backend_table[snd_device] != NULL &&
+            !strcmp(backend_table[snd_device], "headphones-44.1"))
+            port = HEADPHONE_44_1_BACKEND;
+        else
+            port = DEFAULT_CODEC_BACKEND;
+    } else {
+        ALOGV("%s: Invalid device - %d ", __func__, snd_device);
+    }
+
+    ALOGV("%s: backend port - %d", __func__, port);
+    return port;
 }
 
 int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
@@ -2034,6 +2161,7 @@
     audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
     audio_devices_t devices = out->devices;
+    unsigned int sample_rate = out->sample_rate;
 #ifdef RECORD_PLAY_CONCURRENCY
     bool use_voip_out_devices = false;
     bool prop_rec_play_enabled = false;
@@ -2155,7 +2283,10 @@
 
     if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
         devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
-        if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
+        if (OUTPUT_SAMPLING_RATE_44100 == sample_rate &&
+            platform_get_native_support()) {
+            snd_device = SND_DEVICE_OUT_HEADPHONES_44_1;
+        }else if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
             && audio_extn_get_anc_enabled()) {
 #ifdef RECORD_PLAY_CONCURRENCY
             if (use_voip_out_devices) {
@@ -2766,6 +2897,7 @@
 
 static void set_audiocal(void *platform, struct str_parms *parms, char *value, int len) {
     struct platform_data *my_data = (struct platform_data *)platform;
+    struct stream_out out={0};
     acdb_audio_cal_cfg_t cal={0};
     uint8_t *dptr = NULL;
     int32_t dlen;
@@ -2802,7 +2934,8 @@
           if(audio_is_input_device(cal.dev_id)) {
               cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
           } else {
-              cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
+              out.devices = cal.dev_id;
+              cal.snd_dev_id = platform_get_output_snd_device(platform, &out);
           }
         }
         cal.acdb_dev_id = platform_get_snd_device_acdb_id(cal.snd_dev_id);
@@ -2895,6 +3028,7 @@
         }
     }
 #endif
+    native_audio_set_params(platform, parms, value, sizeof(value));
     ALOGV("%s: exit with code(%d)", __func__, ret);
     return ret;
 }
@@ -3001,6 +3135,7 @@
 
 static void get_audiocal(void *platform, void *keys, void *pReply) {
     struct platform_data *my_data = (struct platform_data *)platform;
+    struct stream_out out={0};
     struct str_parms *query = (struct str_parms *)keys;
     struct str_parms *reply=(struct str_parms *)pReply;
     acdb_audio_cal_cfg_t cal={0};
@@ -3031,7 +3166,8 @@
     if(cal.dev_id & AUDIO_DEVICE_BIT_IN) {
         cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
     } else if(cal.dev_id) {
-        cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
+        out.devices = cal.dev_id;
+        cal.snd_dev_id = platform_get_output_snd_device(platform, &out);
     }
     cal.acdb_dev_id =  platform_get_snd_device_acdb_id(cal.snd_dev_id);
     if (cal.acdb_dev_id < 0) {
@@ -3127,6 +3263,7 @@
 
         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VOLUME_BOOST, value);
     }
+    native_audio_get_params(query, reply, value, sizeof(value));
 
     /* Handle audio calibration keys */
     kv_pairs = str_parms_to_str(reply);
@@ -3344,26 +3481,64 @@
     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, "msm8976-tasha-snd-card",
+        sizeof("msm8976-tasha-snd-card")))
+    {
+        /* external codec, for rest/old of the external codecs
+           we dont support this funtionality(chaning AFE params)
+           at the monment
+         */
+        return 1;
+    }
+    else {
+        /* internal codec */
+        return 0;
+    }
+}
+
 int platform_set_codec_backend_cfg(struct audio_device* adev,
+                         snd_device_t snd_device,
                          unsigned int bit_width, unsigned int sample_rate)
 {
-    ALOGV("%s bit width: %d, sample rate: %d", __func__, bit_width, sample_rate);
-
     int ret = 0;
+    int backend_idx = DEFAULT_CODEC_BACKEND;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+    ALOGV("%s bit width: %d, sample rate: %d\n", __func__, bit_width, sample_rate);
+
     const char *snd_card_name = mixer_get_name(adev->mixer);
-    if (bit_width != adev->cur_codec_backend_bit_width) {
-        const char * mixer_ctl_name;
-        if (!strncmp(snd_card_name, "msm8952-tomtom-snd-card",
-                 sizeof("msm8952-tomtom-snd-card"))) {
-            mixer_ctl_name = "SLIM_0_RX Format";
-        }
-        else
-            mixer_ctl_name = "MI2S_RX Format";
+    int is_external_codec = platform_is_external_codec(snd_card_name);
+
+
+
+    backend_idx = platform_get_backend_index(snd_device);
+    ALOGV("%s bit width: %d, sample rate: %d backend_idx - %d\n",
+            __func__, bit_width, sample_rate, backend_idx);
+
+    if (bit_width !=
+        my_data->current_backend_cfg[backend_idx].bit_width) {
+
         struct  mixer_ctl *ctl;
-        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!is_external_codec) {
+            ctl = mixer_get_ctl_by_name(adev->mixer,
+                        "MI2S_RX Format");
+
+        } else {
+            ctl = mixer_get_ctl_by_name(adev->mixer,
+                        my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+        }
         if (!ctl) {
             ALOGE("%s: Could not get ctl for mixer command - %s",
-                    __func__, mixer_ctl_name);
+                    __func__, my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
             return -EINVAL;
         }
 
@@ -3371,10 +3546,12 @@
                 mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else {
             mixer_ctl_set_enum_by_string(ctl, "S16_LE");
-            sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+            if (backend_idx != HEADPHONE_44_1_BACKEND)
+                sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         }
-        adev->cur_codec_backend_bit_width = bit_width;
-        ALOGE("Backend bit width is set to %d ", bit_width);
+        my_data->current_backend_cfg[backend_idx].bit_width = bit_width;
+        ALOGD("%s: %s mixer set to %d bit", __func__,
+            my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
     }
 
     /*
@@ -3386,9 +3563,12 @@
      * Upper limit is inclusive in the sample rate range.
      */
     // TODO: This has to be more dynamic based on policy file
-    if (sample_rate != adev->cur_codec_backend_samplerate) {
+
+    if ((sample_rate != my_data->current_backend_cfg[(int)backend_idx].sample_rate) &&
+        (is_external_codec) ) {
+            /* sample rate update is needed only for external codecs which
+               support 24 bit playback*/
             char *rate_str = NULL;
-            const char * mixer_ctl_name = "SLIM_0_RX SampleRate";
             struct  mixer_ctl *ctl;
 
             switch (sample_rate) {
@@ -3397,10 +3577,12 @@
             case 16000:
             case 22050:
             case 32000:
-            case 44100:
             case 48000:
                 rate_str = "KHZ_48";
                 break;
+            case 44100:
+                rate_str = "KHZ_44P1";
+                break;
             case 64000:
             case 88200:
             case 96000:
@@ -3415,31 +3597,46 @@
                 break;
             }
 
-            ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+            ctl = mixer_get_ctl_by_name(adev->mixer,
+                my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl);
             if(!ctl) {
                 ALOGE("%s: Could not get ctl for mixer command - %s",
-                    __func__, mixer_ctl_name);
+                    __func__, my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl);
                 return -EINVAL;
             }
 
-            ALOGV("Set sample rate as rate_str = %s", rate_str);
+            ALOGD("%s: %s set to %s", __func__,
+                my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl, rate_str);
             mixer_ctl_set_enum_by_string(ctl, rate_str);
-            adev->cur_codec_backend_samplerate = sample_rate;
+            my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
     }
 
     return ret;
 }
 
 bool platform_check_codec_backend_cfg(struct audio_device* adev,
-                                   struct audio_usecase* usecase __unused,
+                                   struct audio_usecase* usecase,
+                                   snd_device_t snd_device,
                                    unsigned int* new_bit_width,
                                    unsigned int* new_sample_rate)
 {
     bool backend_change = false;
     struct listnode *node;
     struct stream_out *out = NULL;
-    unsigned int bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
-    unsigned int sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+    char value[PROPERTY_VALUE_MAX] = {0};
+    unsigned int bit_width;
+    unsigned int sample_rate;
+    int backend_idx = DEFAULT_CODEC_BACKEND;
+    int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+    backend_idx = platform_get_backend_index(snd_device);
+
+    bit_width = *new_bit_width;
+    sample_rate = *new_sample_rate;
+
+    ALOGI("%s Codec selected backend: %d current bit width: %d and sample rate: %d",
+               __func__, backend_idx, bit_width, sample_rate);
 
     // For voice calls use default configuration
     // force routing is not required here, caller will do it anyway
@@ -3460,36 +3657,50 @@
         list_for_each(node, &adev->usecase_list) {
             struct audio_usecase *curr_usecase;
             curr_usecase = node_to_item(node, struct audio_usecase, list);
-            if (curr_usecase->type == PCM_PLAYBACK) {
+            if (curr_usecase->type == PCM_PLAYBACK &&
+                usecase != curr_usecase) {
                 struct stream_out *out =
                            (struct stream_out*) curr_usecase->stream.out;
-                if (out != NULL ) {
-                    ALOGV("Offload playback running bw %d sr %d",
-                              out->bit_width, out->sample_rate);
+                usecase_backend_idx = platform_get_backend_index(curr_usecase->out_snd_device);
+
+                if (out != NULL &&
+                    usecase_backend_idx == backend_idx) {
+                    ALOGV("%s: usecase Offload playback running bw %d sr %d device %s be_idx %d",
+                            __func__, out->bit_width, out->sample_rate,
+                            platform_get_snd_device_name(curr_usecase->out_snd_device), usecase_backend_idx);
                         if (bit_width < out->bit_width)
                             bit_width = out->bit_width;
                         if (sample_rate < out->sample_rate)
                             sample_rate = out->sample_rate;
+                        if (out->sample_rate < OUTPUT_SAMPLING_RATE_44100)
+                            sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
                 }
             }
         }
     }
+    if (backend_idx != HEADPHONE_44_1_BACKEND) {
+        // 16 bit playbacks are allowed through 16 bit/48 khz backend only for
+        // all non-native streams
+        if (16 == bit_width) {
+            sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+            ALOGD("%s: resetting sample_rate back to default, "
+                   "backend_idx: %d", __func__, backend_idx);
+        }
 
-    // 16 bit playback on speakers is allowed through 48 khz backend only
-    if (16 == bit_width) {
-        sample_rate = CODEC_BACKEND_DEFAULT_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) &&
+            (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+            bit_width = (uint32_t)platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
+            sample_rate = CODEC_BACKEND_DEFAULT_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) &&
-        (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
-        bit_width = (uint32_t)platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
-        sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-    }
+    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
     // is not same as current backend comfiguration
-    if ((bit_width != adev->cur_codec_backend_bit_width) ||
-        (sample_rate != adev->cur_codec_backend_samplerate)) {
+    if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
+        (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate)) {
         *new_bit_width = bit_width;
         *new_sample_rate = sample_rate;
         backend_change = true;
@@ -3501,21 +3712,26 @@
 }
 
 bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
-                                              struct audio_usecase *usecase,
-                                              snd_device_t snd_device __unused)
+    struct audio_usecase *usecase, snd_device_t snd_device)
 {
-    ALOGV("platform_check_and_set_codec_backend_cfg usecase = %d",usecase->id );
+    unsigned int new_bit_width;
+    unsigned int new_sample_rate;
+    int backend_idx = DEFAULT_CODEC_BACKEND;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
 
-    unsigned int new_bit_width, old_bit_width;
-    unsigned int new_sample_rate, old_sample_rate;
+    ALOGV("%s: usecase = %d", __func__, usecase->id );
 
-    new_bit_width = old_bit_width = adev->cur_codec_backend_bit_width;
-    new_sample_rate = old_sample_rate = adev->cur_codec_backend_samplerate;
+    backend_idx = platform_get_backend_index(snd_device);
 
-    ALOGW("Codec backend bitwidth %d, samplerate %d", old_bit_width, old_sample_rate);
-    if (platform_check_codec_backend_cfg(adev, usecase,
+    new_bit_width = usecase->stream.out->bit_width;
+    new_sample_rate = usecase->stream.out->sample_rate;
+
+    ALOGI("%s: Usecase bitwidth %d, samplerate %d, backend_idx %d",
+        __func__, new_bit_width, new_sample_rate, backend_idx);
+    if (platform_check_codec_backend_cfg(adev, usecase, snd_device,
                                       &new_bit_width, &new_sample_rate)) {
-        platform_set_codec_backend_cfg(adev, new_bit_width, new_sample_rate);
+        platform_set_codec_backend_cfg(adev, snd_device,
+                                       new_bit_width, new_sample_rate);
         return true;
     }
 
@@ -4182,3 +4398,9 @@
 done:
     return ret;
 }
+
+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 3ce4c57..c63bfe9 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -37,7 +37,11 @@
 /*
  * Below are the devices for which is back end is same, SLIMBUS_0_RX.
  * All these devices are handled by the internal HW codec. We can
- * enable any one of these devices at any time
+ * enable any one of these devices at any time. An exception here is
+ * 44.1k headphone which uses different backend. This is filtered
+ * as different hal internal device in the code but remains same
+ * as standard android device AUDIO_DEVICE_OUT_WIRED_HEADPHONE
+ * for other layers.
  */
 #define AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND \
     (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
@@ -163,13 +167,16 @@
 };
 
 #define DEFAULT_OUTPUT_SAMPLING_RATE 48000
-#define OUTPUT_SAMPLING_RATE_44100   44100
-
+#define OUTPUT_SAMPLING_RATE_44100      44100
+#define MAX_PORT                        6
+#define ALL_CODEC_BACKEND_PORT          0
+#define HEADPHONE_44_1_BACKEND_PORT     5
 enum {
     DEFAULT_CODEC_BACKEND,
     HEADPHONE_44_1_BACKEND,
     MAX_CODEC_BACKENDS
 };
+#define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
 
 #define ALL_SESSION_VSID                0xFFFFFFFF
 #define DEFAULT_MUTE_RAMP_DURATION_MS   20
@@ -189,8 +196,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
 
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 5fab099..861790e 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1098,6 +1098,11 @@
     return 0;
 }
 
+bool platform_use_small_buffer(audio_offload_info_t* info)
+{
+    return false;
+}
+
 int platform_get_edid_info(void *platform __unused)
 {
    return -ENOSYS;
@@ -1166,3 +1171,9 @@
 {
     return -ENOSYS;
 }
+
+bool platform_send_gain_dep_cal(void *platform __unused,
+                                int level __unused)
+{
+    return 0;
+}
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index c96d11e..7849644 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -134,6 +134,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,
@@ -278,6 +282,12 @@
         hw_info->snd_devices = (snd_device_t *)tomtom_liquid_variant_devices;
         hw_info->num_snd_devices = ARRAY_SIZE(tomtom_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 d9921d0..875cc2c 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"
@@ -129,7 +130,6 @@
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_ANC_CAL] = "anc_cal",
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
-        [WCD9XXX_MAD_CAL] = "mad_cal",
 };
 
 enum {
@@ -156,6 +156,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);
@@ -181,6 +187,7 @@
     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;
@@ -213,6 +220,7 @@
     acdb_send_common_top_t     acdb_send_common_top;
 
     void *hw_info;
+    acdb_send_gain_dep_cal_t   acdb_send_gain_dep_cal;
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
@@ -708,6 +716,55 @@
 #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 ||
+                usecase->stream.out->devices == AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
+
+                ALOGV("%s: out device is %d", __func__,  usecase->out_snd_device);
+                app_type = usecase->stream.out->app_type_cfg.app_type;
+                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_echo_reference(void *platform, bool enable)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -991,8 +1048,6 @@
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
 
-        if (!strcmp(cal_name_info[type], "mad_cal"))
-            calib.acdb_id = SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID;
         calib.get_size = 1;
         ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
                                                                  &calib);
@@ -1289,6 +1344,12 @@
             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");
@@ -3249,6 +3310,11 @@
     return fragment_size;
 }
 
+bool platform_use_small_buffer(audio_offload_info_t* info)
+{
+    return OFFLOAD_USE_SMALL_BUFFER;
+}
+
 int platform_set_codec_backend_cfg(struct audio_device* adev,
                          snd_device_t snd_device,
                          unsigned int bit_width, unsigned int sample_rate)
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 4b90f8b..2247933 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -185,8 +185,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
 
@@ -227,6 +227,8 @@
 #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
diff --git a/hal/platform_api.h b/hal/platform_api.h
index d9fe0c0..921ff0b 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -30,6 +30,7 @@
 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);
+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);
@@ -94,6 +95,7 @@
 struct audio_offload_info_t;
 uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
 uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);
+bool platform_use_small_buffer(audio_offload_info_t* info);
 uint32_t platform_get_compress_passthrough_buffer_size(audio_offload_info_t* info);
 
 bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
diff --git a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
index 6af9269..4cfee1b 100644
--- a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
+++ b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
@@ -4208,6 +4208,16 @@
                buffer->nOffset = 0;
                buffer->nTimeStamp = nTimestamp;
                frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
+
+               if (errno == ENETRESET)
+               {
+                   ALOGE("In SSR, return error to close the session");
+                   m_cb.EventHandler(&m_cmp,
+                       m_app_data,
+                      OMX_EventError,
+                      OMX_ErrorHardware,
+                      0, NULL );
+               }
                return OMX_ErrorNone;
            }
         }
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 71a210f..192320a 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -14,8 +14,12 @@
 	virtualizer.c \
 	reverb.c \
 	effect_api.c \
-	effect_util.c \
-        hw_accelerator.c
+	effect_util.c
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HW_ACCELERATED_EFFECTS)),true)
+    LOCAL_CFLAGS += -DHW_ACCELERATED_EFFECTS
+    LOCAL_SRC_FILES += hw_accelerator.c
+endif
 
 LOCAL_CFLAGS+= -O2 -fvisibility=hidden
 
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index e38a41c..6f1bdfa 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -38,6 +38,7 @@
 #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>
@@ -69,7 +70,9 @@
         &ins_env_reverb_descriptor,
         &aux_preset_reverb_descriptor,
         &ins_preset_reverb_descriptor,
+#ifdef HW_ACCELERATED_EFFECTS
         &hw_accelerator_descriptor,
+#endif
         NULL,
 };
 
@@ -302,9 +305,6 @@
         goto exit;
     }
 
-    if (out_ctxt->mixer)
-        mixer_close(out_ctxt->mixer);
-
     list_for_each(fx_node, &out_ctxt->effects_list) {
         effect_context_t *fx_ctxt = node_to_item(fx_node,
                                                  effect_context_t,
@@ -313,6 +313,9 @@
             fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
     }
 
+    if (out_ctxt->mixer)
+        mixer_close(out_ctxt->mixer);
+
     list_remove(&out_ctxt->outputs_list_node);
 
 #ifdef DTS_EAGLE
@@ -604,6 +607,7 @@
             reverb_preset_init(reverb_ctxt);
         }
         reverb_ctxt->ctl = NULL;
+#ifdef HW_ACCELERATED_EFFECTS
     } else if (memcmp(uuid, &hw_accelerator_descriptor.uuid,
                sizeof(effect_uuid_t)) == 0) {
         hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)
@@ -625,6 +629,7 @@
         context->ops.process = hw_accelerator_process;
 
         context->desc = &hw_accelerator_descriptor;
+#endif
     } else {
         return -EINVAL;
     }
@@ -911,6 +916,7 @@
 
         } break;
 
+#ifdef HW_ACCELERATED_EFFECTS
     case EFFECT_CMD_HW_ACC: {
         ALOGV("EFFECT_CMD_HW_ACC cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
               cmdSize, pCmdData, *replySize, pReplyData);
@@ -925,6 +931,7 @@
         context->hw_acc_enabled = (value > 0) ? true : false;
         break;
     }
+#endif
     default:
         if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
             status = context->ops.command(context, cmdCode, cmdSize,
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index e15db17..16c370b 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 8f7a604..52f623d 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"
 
 #ifdef LOG_TAG
diff --git a/voice_processing/voice_processing.c b/voice_processing/voice_processing.c
index 1d18a3d..72e4d84 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 <cutils/log.h>
 #include <cutils/list.h>