Merge commit 'eb9127a942289de0cf9587d7456cc6c9a44eb411' into remote_branch

Change-Id: Ic630ae55085197a1bc7b79c726f7a0e39b9927b4
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 523a875..8e5d64e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -428,7 +428,6 @@
                                   audio_format_t format,
                                   uint32_t sample_rate,
                                   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);
 void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
index 52d7abb..7608a61 100644
--- a/hal/audio_extn/dts_eagle.c
+++ b/hal/audio_extn/dts_eagle.c
@@ -39,7 +39,6 @@
 #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
 
@@ -117,7 +116,7 @@
     }
 
     if (!sent) {
-        int fd = open(DEVICE_NODE, O_RDWR);
+        int fd = open(GENERIC_AUDIO_DEVICE_NODE, O_RDWR);
 
         if (get) {
             ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to retrieve directly from cache", __func__);
@@ -137,7 +136,7 @@
             }
             close(fd);
         } else {
-            ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, DEVICE_NODE);
+            ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, GENERIC_AUDIO_DEVICE_NODE);
             ret = -EINVAL;
         }
     }
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index ed3776c..efc2307 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -243,7 +243,20 @@
         if (ret >= 0) {
             val = atoi(value);
             if(val > 0)
-                select_devices(adev, USECASE_AUDIO_PLAYBACK_FM);
+                /*
+                 * Only when wsa does present and is in analog mode,
+                 * fm will stop/start here.
+                 * To-do: when the kernel codec type query change
+                 * is ready, enum of wsa mode should be checked here.
+                 * Currently, platform_get_wsa_mode will directly return
+                 * 1 when wsa is in analog mode.
+                 */
+                if (platform_get_wsa_mode(adev->platform) == 1) {
+                    fm_stop(adev);
+                    fm_start(adev);
+                } else {
+                    select_devices(adev, USECASE_AUDIO_PLAYBACK_FM);
+                }
         }
     }
     if (fmmod.restart_fm && (fmmod.scard_state == SND_CARD_STATE_ONLINE)) {
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 15f2a3a..e5201cc 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -779,7 +779,6 @@
                                                 __func__, NUM_ATTEMPTS);
                        t0_spk_1 = SAFE_SPKR_TEMP_Q6;
                    }
-                   fclose(fp);
                }
                if (spk_2_tzn > 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
@@ -810,7 +809,6 @@
                                                 __func__, NUM_ATTEMPTS);
                        t0_spk_2 = SAFE_SPKR_TEMP_Q6;
                    }
-                   fclose(fp);
                }
            }
            pthread_mutex_unlock(&adev->lock);
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index dbd54f7..75bb336 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -436,6 +436,7 @@
      * than all sample rates in list for the input bit width.
      */
     sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+
     list_for_each(node_i, &so_info->sample_rate_list) {
         ss_info = node_to_item(node_i, struct stream_sample_rate, list);
         if ((sample_rate <= ss_info->sample_rate) &&
@@ -443,7 +444,7 @@
             app_type_cfg->app_type = so_info->app_type_cfg.app_type;
             app_type_cfg->sample_rate = sample_rate;
             app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
-            ALOGV("%s Assuming default sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
+            ALOGV("%s Assuming sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
                    __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
             return true;
         }
@@ -458,14 +459,12 @@
                                   audio_format_t format,
                                   uint32_t sample_rate,
                                   uint32_t bit_width,
-                                  audio_channel_mask_t channel_mask,
                                   struct stream_app_type_cfg *app_type_cfg)
 {
     struct listnode *node_i, *node_j, *node_k;
     struct streams_output_cfg *so_info;
     struct stream_format *sf_info;
     struct stream_sample_rate *ss_info;
-    char value[PROPERTY_VALUE_MAX] = {0};
 
     if ((24 == bit_width) &&
         (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
@@ -476,16 +475,6 @@
         ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
     }
 
-    property_get("audio.playback.mch.downsample",value,"");
-    if (!strncmp("true", value, sizeof("true"))) {
-        if ((popcount(channel_mask) > 2) &&
-                (sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
-                !(flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))  {
-                    sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-                    ALOGD("%s: MCH session defaulting sample rate to %d",
-                               __func__, sample_rate);
-        }
-    }
     ALOGV("%s: flags: %x, format: %x sample_rate %d",
            __func__, flags, format, sample_rate);
     list_for_each(node_i, streams_output_cfg_list) {
@@ -527,7 +516,6 @@
     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;
-    char value[PROPERTY_VALUE_MAX] = {0};
 
     ALOGV("%s", __func__);
 
@@ -573,18 +561,14 @@
     if ((24 == usecase->stream.out->bit_width) &&
         (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
         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)) {
+        sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
     } else {
         sample_rate = 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))
-           sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-    }
-
     app_type_cfg[len++] = out->app_type_cfg.app_type;
     app_type_cfg[len++] = acdb_dev_id;
     if (((out->format == AUDIO_FORMAT_E_AC3) ||
@@ -593,6 +577,7 @@
         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);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7c3848b..126f3b0 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -582,6 +582,8 @@
     struct audio_usecase *usecase;
     bool switch_device[AUDIO_USECASE_MAX];
     int i, num_uc_to_switch = 0;
+    int backend_idx = DEFAULT_CODEC_BACKEND;
+    int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
 
     /*
      * This function is to make sure that all the usecases that are active on
@@ -598,23 +600,34 @@
      * If there is a backend configuration change for the device when a
      * new stream starts, then ADM needs to be closed and re-opened with the new
      * configuraion. This call check if we need to re-route all the streams
-     * associated with the backend. Touch tone + 24 bit playback.
+     * associated with the backend. Touch tone + 24 bit + native playback.
      */
-    bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
-
+    bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
+                         snd_device);
+    backend_idx = platform_get_backend_index(snd_device);
     /* Disable all the usecases on the shared backend other than the
-       specified usecase */
+     * specified usecase.
+     */
     for (i = 0; i < AUDIO_USECASE_MAX; i++)
         switch_device[i] = false;
 
     list_for_each(node, &adev->usecase_list) {
         usecase = node_to_item(node, struct audio_usecase, list);
+
+        if (usecase == uc_info)
+            continue;
+        usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
+        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));
+
         if (usecase->type != PCM_CAPTURE &&
-                usecase != uc_info &&
                 (usecase->out_snd_device != snd_device || force_routing)  &&
-                usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
-            ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
-                  __func__, use_case_table[usecase->id],
+                usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
+                usecase_backend_idx == backend_idx) {
+            ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
+                  use_case_table[usecase->id],
                   platform_get_snd_device_name(usecase->out_snd_device));
             disable_audio_route(adev, usecase);
             switch_device[usecase->id] = true;
@@ -814,7 +827,7 @@
         (usecase->type == VOIP_CALL)  ||
         (usecase->type == PCM_HFP_CALL)) {
         out_snd_device = platform_get_output_snd_device(adev->platform,
-                                                        usecase->stream.out->devices);
+                                                        usecase->stream.out);
         in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
         usecase->devices = usecase->stream.out->devices;
     } else {
@@ -854,7 +867,7 @@
             in_snd_device = SND_DEVICE_NONE;
             if (out_snd_device == SND_DEVICE_NONE) {
                 out_snd_device = platform_get_output_snd_device(adev->platform,
-                                            usecase->stream.out->devices);
+                                            usecase->stream.out);
                 if (usecase->stream.out == adev->primary_output &&
                         adev->active_input &&
                         adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
@@ -899,6 +912,9 @@
         (usecase->in_snd_device != SND_DEVICE_NONE) &&
         (usecase->out_snd_device != SND_DEVICE_NONE)) {
         status = platform_switch_voice_call_device_pre(adev->platform);
+        /* Disable sidetone only if voice call already exists */
+        if (voice_is_call_state_active(adev))
+            voice_set_sidetone(adev, usecase->out_snd_device, false);
     }
 
     /* Disable current sound devices */
@@ -941,6 +957,9 @@
                                                         out_snd_device,
                                                         in_snd_device);
         enable_audio_route_for_voice_usecases(adev, usecase);
+        /* Enable sidetone only if voice call already exists */
+        if (voice_is_call_state_active(adev))
+            voice_set_sidetone(adev, out_snd_device, true);
     }
 
     usecase->in_snd_device = in_snd_device;
@@ -954,7 +973,6 @@
                                                 usecase->stream.out->format,
                                                 usecase->stream.out->sample_rate,
                                                 usecase->stream.out->bit_width,
-                                                usecase->stream.out->channel_mask,
                                                 &usecase->stream.out->app_type_cfg);
         ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
     }
@@ -2979,8 +2997,7 @@
     audio_extn_utils_update_stream_app_type_cfg(adev->platform,
                                                 &adev->streams_output_cfg_list,
                                                 devices, flags, format, out->sample_rate,
-                                                out->bit_width, out->channel_mask,
-                                                &out->app_type_cfg);
+                                                out->bit_width, &out->app_type_cfg);
     if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
         (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
         /* Ensure the default output is not selected twice */
@@ -3135,6 +3152,12 @@
         } 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");
+
+            }
         }
     }
 
@@ -3640,8 +3663,6 @@
     adev->bluetooth_nrec = true;
     adev->acdb_settings = TTY_MODE_OFF;
     /* adev->cur_hdmi_channels = 0;  by calloc() */
-    adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-    adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
     voice_init(adev);
     list_init(&adev->usecase_list);
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index 1a882db..fb36a95 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -245,6 +245,12 @@
         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")) {
+       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, "msm8952-skum-snd-card")) {
         strlcpy(hw_info->type, "", sizeof(hw_info->type));
         strlcpy(hw_info->name, "msm8952", sizeof(hw_info->name));
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 765aea1..dfdcf7d 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -58,6 +58,7 @@
 #define MIXER_XML_PATH_WCD9306 "/system/etc/mixer_paths_wcd9306.xml"
 #define MIXER_XML_PATH_WCD9330 "/system/etc/mixer_paths_wcd9330.xml"
 #define MIXER_XML_PATH_WCD9335 "/system/etc/mixer_paths_wcd9335.xml"
+#define MIXER_XML_PATH_SKUN "/system/etc/mixer_paths_qrd_skun.xml"
 #define PLATFORM_INFO_XML_PATH      "/system/etc/audio_platform_info.xml"
 #define PLATFORM_INFO_XML_PATH_EXTCODEC  "/system/etc/audio_platform_info_extcodec.xml"
 
@@ -70,17 +71,14 @@
 #define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
 #define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
 /* Used in calculating fragment size for pcm offload */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 1000 /* 1 sec */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 80 /* 80 millisecs */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS 20 /* 20 millisecs */
-#define PCM_OFFLOAD_BUFFER_DURATION_MAX 1200  /* 1200 millisecs */
+#define PCM_OFFLOAD_BUFFER_DURATION 40 /* 40 millisecs */
 
 /* MAX PCM fragment size cannot be increased  further due
  * to flinger's cblk size of 1mb,and it has to be a multiple of
  * 24 - lcm of channels supported by DSP
  */
 #define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
-#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (4 * 1024)
+#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE  512
 
 /*
  * Offload buffer size for compress passthrough
@@ -192,6 +190,20 @@
 typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
 typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
 
+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;
@@ -208,6 +220,7 @@
     bool hd_voice;
     bool ec_ref_enabled;
     bool is_wsa_speaker;
+    bool is_acdb_initialized;
     /* Audio calibration related functions */
     void                       *acdb_handle;
     int                        voice_feature_set;
@@ -226,6 +239,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;
@@ -311,6 +325,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",
@@ -415,6 +430,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,
@@ -521,6 +537,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)},
@@ -728,7 +745,9 @@
          !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")))
+                  sizeof("msm8976-tasha-snd-card")) ||
+         !strncmp(snd_card_name, "msm8976-tasha-skun-snd-card",
+                  sizeof("msm8976-tasha-skun-snd-card")))
      {
          ALOGI("%s: snd_card_name: %s",__func__,snd_card_name);
          is_external_codec = true;
@@ -832,6 +851,14 @@
         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-tasha-skun-snd-card",
+                sizeof("msm8976-tasha-skun-snd-card"))) {
+        strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUN,
+                sizeof(MIXER_XML_PATH_SKUN));
+        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, "msm8909-skua-snd-card",
                  sizeof("msm8909-skua-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUA,
@@ -1075,7 +1102,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.
@@ -1097,6 +1124,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)
@@ -1219,6 +1247,37 @@
         ALOGE("%s: Could not send anc cal", __FUNCTION__);
 }
 
+int platform_acdb_init(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    char *cvd_version = NULL;
+    int key = 0;
+    const char *snd_card_name;
+    int result;
+    char value[PROPERTY_VALUE_MAX];
+    cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
+    if (!cvd_version)
+        ALOGE("Failed to allocate cvd version");
+    else
+        get_cvd_version(cvd_version, my_data->adev);
+
+    property_get("audio.ds1.metainfo.key",value,"0");
+    key = atoi(value);
+    snd_card_name = mixer_get_name(my_data->adev->mixer);
+    result = my_data->acdb_init(snd_card_name, cvd_version, key);
+    if (cvd_version)
+        free(cvd_version);
+    if (!result) {
+        my_data->is_acdb_initialized = true;
+        ALOGD("ACDB initialized");
+        audio_hwdep_send_cal(my_data);
+    } else {
+        my_data->is_acdb_initialized = false;
+        ALOGD("ACDB initialization failed");
+    }
+    return result;
+}
+
 void *platform_init(struct audio_device *adev)
 {
     char platform[PROPERTY_VALUE_MAX];
@@ -1231,6 +1290,7 @@
     char *cvd_version = NULL;
     const char *mixer_ctl_name = "Set HPX ActiveBe";
     struct mixer_ctl *ctl = NULL;
+    int idx;
 
     my_data = calloc(1, sizeof(struct platform_data));
     if (!my_data) {
@@ -1349,8 +1409,6 @@
         acdb_device_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 131;
         acdb_device_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 131;
     }
-    property_get("audio.ds1.metainfo.key",value,"0");
-    key = atoi(value);
 
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
@@ -1407,15 +1465,7 @@
             ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
             goto acdb_init_fail;
         }
-
-        cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
-        if (!cvd_version)
-            ALOGE("Failed to allocate cvd version");
-        else
-            get_cvd_version(cvd_version, adev);
-        my_data->acdb_init(snd_card_name, cvd_version, key);
-        if (cvd_version)
-            free(cvd_version);
+        platform_acdb_init(my_data);
     }
     audio_extn_pm_vote();
 
@@ -1474,6 +1524,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;
 }
 
@@ -1511,6 +1581,13 @@
     audio_extn_dap_hal_deinit();
 }
 
+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;
+}
+
 const char *platform_get_snd_device_name(snd_device_t snd_device)
 {
     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
@@ -1730,6 +1807,109 @@
     return backend_bit_width_table[snd_device];
 }
 
+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_native_support()
+{
+    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,
                                     int app_type, int sample_rate)
 {
@@ -2016,12 +2196,14 @@
     return ret;
 }
 
-snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
+snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
     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;
@@ -2046,7 +2228,7 @@
         goto exit;
     }
 
-    if (popcount(devices) == 2) {
+    if (popcount(devices) == 2 && !voice_is_in_call(adev)) {
         if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
                         AUDIO_DEVICE_OUT_SPEAKER)) {
             if (my_data->external_spk_1)
@@ -2085,7 +2267,8 @@
         goto exit;
     }
 
-    if (voice_is_in_call(adev) || voice_extn_compress_voip_is_active(adev)) {
+    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) {
             if ((adev->voice.tty_mode != TTY_MODE_OFF) &&
@@ -2142,7 +2325,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) {
@@ -2234,8 +2420,8 @@
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
     if (my_data->external_mic) {
-        if ((out_device != AUDIO_DEVICE_NONE && voice_is_in_call(adev)) ||
-            voice_extn_compress_voip_is_active(adev) || audio_extn_hfp_is_active(adev)) {
+        if ((out_device != AUDIO_DEVICE_NONE) && ((mode == AUDIO_MODE_IN_CALL) ||
+            voice_extn_compress_voip_is_active(adev) || audio_extn_hfp_is_active(adev))) {
             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
                out_device & AUDIO_DEVICE_OUT_EARPIECE ||
                out_device & AUDIO_DEVICE_OUT_SPEAKER )
@@ -2249,7 +2435,7 @@
     if (snd_device != AUDIO_DEVICE_NONE)
         goto exit;
 
-    if ((out_device != AUDIO_DEVICE_NONE) && ((voice_is_in_call(adev)) ||
+    if ((out_device != AUDIO_DEVICE_NONE) && ((mode == AUDIO_MODE_IN_CALL) ||
         voice_extn_compress_voip_is_active(adev) || audio_extn_hfp_is_active(adev))) {
         if ((adev->voice.tty_mode != TTY_MODE_OFF) &&
             !voice_extn_compress_voip_is_active(adev)) {
@@ -2756,6 +2942,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;
@@ -2792,7 +2979,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);
@@ -2885,6 +3073,7 @@
         }
     }
 #endif
+    native_audio_set_params(platform, parms, value, sizeof(value));
     ALOGV("%s: exit with code(%d)", __func__, ret);
     return ret;
 }
@@ -2991,6 +3180,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};
@@ -3021,7 +3211,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) {
@@ -3117,6 +3308,7 @@
 
         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VOLUME_BOOST, value);
     }
+    native_audio_get_params(query, reply, value, sizeof(value));
 
     ret = str_parms_get_str(query, AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED,
                                     value, sizeof(value));
@@ -3339,25 +3531,13 @@
 {
     uint32_t fragment_size = 0;
     uint32_t bits_per_sample = 16;
-    uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
+    uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
 
     if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
         bits_per_sample = 32;
     }
 
-    if (platform_use_small_buffer(info)) {
-        pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
-    } else {
-        if (!info->has_video) {
-            pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_MAX;
-        } else if (info->has_video && info->is_streaming) {
-            pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING;
-        } else if (info->has_video) {
-            pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV;
-        }
-    }
-
-    //duration is set to 20 ms worth of stereo data at 48Khz
+    //duration is set to 40 ms worth of stereo data at 48Khz
     //with 16 bit per sample, modify this when the channel
     //configuration is different
     fragment_size = (pcm_offload_time
@@ -3377,29 +3557,61 @@
     return fragment_size;
 }
 
+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")) ||
+        !strncmp(snd_card_name, "msm8976-tasha-skun-snd-card",
+        sizeof("msm8976-tasha-skun-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;
-    const char *snd_card_name = mixer_get_name(adev->mixer);
+    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);
 
-    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")) ||
-            !strncmp(snd_card_name, "msm8976-tasha-snd-card",
-                sizeof("msm8976-tasha-snd-card"))) {
-            mixer_ctl_name = "SLIM_0_RX Format";
-        }
-        else
-            mixer_ctl_name = "MI2S_RX Format";
+    const char *snd_card_name = mixer_get_name(adev->mixer);
+    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;
         }
 
@@ -3407,10 +3619,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);
     }
 
     /*
@@ -3422,9 +3636,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) {
@@ -3433,10 +3650,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:
@@ -3451,32 +3670,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
@@ -3497,52 +3730,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;
+        }
     }
-
-    //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)) {
-           sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-          /* update out sample rate to reflect current backend sample rate  */
-           out->sample_rate = 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) &&
-        (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;
@@ -3553,20 +3784,27 @@
     return backend_change;
 }
 
-bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase)
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
+    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;
     }
 
@@ -3819,10 +4057,15 @@
         ALOGE("%s: Invalid channel mapping used", __func__);
         return -EINVAL;
     }
-    strlcpy(mixer_ctl_name, "Playback Channel Map", sizeof(mixer_ctl_name));
+
+    /*
+     * If snd_id is greater than 0, stream channel mapping
+     * If snd_id is below 0, typically -1, device channel mapping
+     */
     if (snd_id >= 0) {
-        snprintf(device_num, sizeof(device_num), "%d", snd_id);
-        strlcat(mixer_ctl_name, device_num, sizeof(device_num));
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback Channel Map%d", snd_id);
+    } else {
+        strlcpy(mixer_ctl_name, "Playback Device Channel Map", sizeof(mixer_ctl_name));
     }
 
     ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);
@@ -4238,3 +4481,16 @@
 done:
     return ret;
 }
+
+int platform_get_wsa_mode(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    char *snd_card_name;
+
+    snd_card_name = mixer_get_name(my_data->adev->mixer);
+    if ((!strcmp(snd_card_name, "msm8952-skum-snd-card")) ||
+        (!strcmp(snd_card_name, "msm8952-snd-card-mtp")))
+        return 1;
+    else
+        return 0;
+}
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index d564839..9f0015a 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 | \
@@ -60,6 +64,7 @@
     SND_DEVICE_OUT_SPEAKER_REVERSE,
     SND_DEVICE_OUT_SPEAKER_WSA,
     SND_DEVICE_OUT_HEADPHONES,
+    SND_DEVICE_OUT_HEADPHONES_44_1,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2,
@@ -162,6 +167,16 @@
 };
 
 #define DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#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
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index bceaf96..038effa 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -676,7 +676,7 @@
         goto exit;
     }
 
-    if (voice_is_in_call(adev)) {
+    if (mode == AUDIO_MODE_IN_CALL) {
         if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
             devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
             if (adev->voice.tty_mode == TTY_MODE_FULL)
@@ -768,7 +768,7 @@
 
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
-    if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
+    if ((out_device != AUDIO_DEVICE_NONE) && (mode == AUDIO_MODE_IN_CALL)) {
         if (adev->voice.tty_mode != TTY_MODE_OFF) {
             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
                 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
@@ -1180,3 +1180,8 @@
 {
     return -ENOSYS;
 }
+
+int platform_get_wsa_mode(void *platform)
+{
+    return 0;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 461c9a2..8c1a768 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -65,17 +65,14 @@
 #define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
 
 /* Used in calculating fragment size for pcm offload */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 1000 /* 1 sec */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 80 /* 80 millisecs */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS 20 /* 20 millisecs */
-#define PCM_OFFLOAD_BUFFER_DURATION_MAX 1200  /* 1200 millisecs */
+#define PCM_OFFLOAD_BUFFER_DURATION 40 /* 40 millisecs */
 
 /* MAX PCM fragment size cannot be increased  further due
  * to flinger's cblk size of 1mb,and it has to be a multiple of
  * 24 - lcm of channels supported by DSP
  */
 #define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
-#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (4 * 1024)
+#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE 512
 
 /*
  * Offload buffer size for compress passthrough
@@ -171,6 +168,20 @@
 typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
 typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
 
+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;
@@ -187,6 +198,7 @@
     bool hd_voice;
     bool ec_ref_enabled;
     bool is_i2s_ext_modem;
+    bool is_acdb_initialized;
     /* Audio calibration related functions */
     void                       *acdb_handle;
     int                        voice_feature_set;
@@ -203,6 +215,7 @@
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
+    codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
 };
 
 static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -287,6 +300,7 @@
     [SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
     [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",
@@ -384,6 +398,7 @@
     [SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 130,
     [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] = 130,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 130,
@@ -475,7 +490,7 @@
 
 #define TO_NAME_INDEX(X)   #X, X
 
-/* Used to get index from parsed sting */
+/* Used to get index from parsed string */
 static struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
     {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
@@ -483,6 +498,7 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
     {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)},
@@ -878,7 +894,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.
@@ -901,6 +917,8 @@
     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] = strdup("headphones");
+    backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
 }
 
 void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1016,6 +1034,37 @@
         ALOGE("%s: Could not send anc cal", __FUNCTION__);
 }
 
+int platform_acdb_init(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    char *cvd_version = NULL;
+    int key = 0;
+    const char *snd_card_name;
+    int result;
+    char value[PROPERTY_VALUE_MAX];
+    cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
+    if (!cvd_version)
+        ALOGE("Failed to allocate cvd version");
+    else
+        get_cvd_version(cvd_version, my_data->adev);
+
+    property_get("audio.ds1.metainfo.key",value,"0");
+    key = atoi(value);
+    snd_card_name = mixer_get_name(my_data->adev->mixer);
+    result = my_data->acdb_init(snd_card_name, cvd_version, key);
+    if (cvd_version)
+        free(cvd_version);
+    if (!result) {
+        my_data->is_acdb_initialized = true;
+        ALOGD("ACDB initialized");
+        audio_hwdep_send_cal(my_data);
+    } else {
+        my_data->is_acdb_initialized = false;
+        ALOGD("ACDB initialization failed");
+    }
+    return result;
+}
+
 void *platform_init(struct audio_device *adev)
 {
     char platform[PROPERTY_VALUE_MAX];
@@ -1030,6 +1079,7 @@
     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));
 
@@ -1182,8 +1232,6 @@
             my_data->fluence_mode = FLUENCE_BROADSIDE;
         }
     }
-    property_get("audio.ds1.metainfo.key",value,"0");
-    key = atoi(value);
 
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
@@ -1241,15 +1289,7 @@
             goto acdb_init_fail;
         }
 
-        cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
-        if (!cvd_version)
-            ALOGE("failed to allocate cvd_version");
-        else
-            get_cvd_version(cvd_version, adev);
-
-        my_data->acdb_init(snd_card_name, cvd_version, key);
-        if (cvd_version)
-            free(cvd_version);
+        platform_acdb_init(my_data);
     }
 
     /* Configure active back end for HPX*/
@@ -1300,6 +1340,24 @@
     /* init audio device arbitration */
     audio_extn_dev_arbi_init();
 
+    /* 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;
 }
@@ -1338,6 +1396,13 @@
     audio_extn_dap_hal_deinit();
 }
 
+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;
+}
+
 const char *platform_get_snd_device_name(snd_device_t snd_device)
 {
     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
@@ -1565,6 +1630,111 @@
     return backend_bit_width_table[snd_device];
 }
 
+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_native_support()
+{
+    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") == 0)
+            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,
                                     int app_type, int sample_rate)
 {
@@ -1575,7 +1745,7 @@
 
     if (usecase->type == PCM_PLAYBACK)
         snd_device = platform_get_output_snd_device(adev->platform,
-                                            usecase->stream.out->devices);
+                                            usecase->stream.out);
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
         snd_device = platform_get_input_snd_device(adev->platform,
                                             adev->primary_output->devices);
@@ -1856,12 +2026,14 @@
     return ret;
 }
 
-snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
+snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
     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;
 
     audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
                                 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
@@ -1874,7 +2046,7 @@
         goto exit;
     }
 
-    if (popcount(devices) == 2) {
+    if (popcount(devices) == 2 && !voice_is_in_call(adev)) {
         if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
                         AUDIO_DEVICE_OUT_SPEAKER)) {
             if (my_data->external_spk_1)
@@ -1913,7 +2085,7 @@
         goto exit;
     }
 
-    if (voice_is_in_call(adev) ||
+    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) {
@@ -1974,8 +2146,11 @@
                 snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET;
             else
                 snd_device = SND_DEVICE_OUT_ANC_HEADSET;
-        } else
-            snd_device = SND_DEVICE_OUT_HEADPHONES;
+        } else if (platform_get_native_support() &&
+                    OUTPUT_SAMPLING_RATE_44100 == sample_rate)
+                snd_device = SND_DEVICE_OUT_HEADPHONES_44_1;
+          else
+                snd_device = SND_DEVICE_OUT_HEADPHONES;
     } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
         if (my_data->external_spk_1)
             snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_1;
@@ -2033,8 +2208,8 @@
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
     if (my_data->external_mic) {
-        if ((out_device != AUDIO_DEVICE_NONE && voice_is_in_call(adev)) ||
-            voice_extn_compress_voip_is_active(adev) || audio_extn_hfp_is_active(adev)) {
+        if ((out_device != AUDIO_DEVICE_NONE) && ((mode == AUDIO_MODE_IN_CALL) ||
+            voice_extn_compress_voip_is_active(adev) || audio_extn_hfp_is_active(adev))) {
             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
                out_device & AUDIO_DEVICE_OUT_EARPIECE ||
                out_device & AUDIO_DEVICE_OUT_SPEAKER )
@@ -2048,7 +2223,7 @@
     if (snd_device != AUDIO_DEVICE_NONE)
         goto exit;
 
-    if ((out_device != AUDIO_DEVICE_NONE) && ((voice_is_in_call(adev)) ||
+    if ((out_device != AUDIO_DEVICE_NONE) && ((mode == AUDIO_MODE_IN_CALL) ||
         voice_extn_compress_voip_is_active(adev) || audio_extn_hfp_is_active(adev))) {
         if ((adev->voice.tty_mode != TTY_MODE_OFF) &&
             !voice_extn_compress_voip_is_active(adev)) {
@@ -2528,6 +2703,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;
     acdb_audio_cal_cfg_t cal={0};
     uint8_t *dptr = NULL;
     int32_t dlen;
@@ -2564,7 +2740,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);
@@ -2680,7 +2857,7 @@
 
     /* handle audio calibration parameters */
     set_audiocal(platform, parms, value, len);
-
+    native_audio_set_params(platform, parms, value, len);
 done:
     ALOGV("%s: exit with code(%d)", __func__, ret);
     if(kv_pairs != NULL)
@@ -2792,6 +2969,7 @@
 
 static void get_audiocal(void *platform, void *keys, void *pReply) {
     struct platform_data *my_data = (struct platform_data *)platform;
+    struct stream_out out;
     struct str_parms *query = (struct str_parms *)keys;
     struct str_parms *reply=(struct str_parms *)pReply;
     acdb_audio_cal_cfg_t cal={0};
@@ -2822,7 +3000,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) {
@@ -2921,6 +3100,7 @@
 
     /* Handle audio calibration keys */
     get_audiocal(platform, query, reply);
+    native_audio_get_params(query, reply, value, sizeof(value));
 
 done:
     kv_pairs = str_parms_to_str(reply);
@@ -3026,25 +3206,13 @@
 {
     uint32_t fragment_size = 0;
     uint32_t bits_per_sample = 16;
-    uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
+    uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
 
     if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
         bits_per_sample = 32;
     }
 
-    if (info->use_small_bufs) {
-        pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
-    } else {
-        if (!info->has_video) {
-            pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_MAX;
-        } else if (info->has_video && info->is_streaming) {
-            pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING;
-        } else if (info->has_video) {
-            pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV;
-        }
-    }
-
-    //duration is set to 20 ms worth of stereo data at 48Khz
+    //duration is set to 40 ms worth of stereo data at 48Khz
     //with 16 bit per sample, modify this when the channel
     //configuration is different
     fragment_size = (pcm_offload_time
@@ -3070,29 +3238,39 @@
 }
 
 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;
-    if (bit_width != adev->cur_codec_backend_bit_width) {
-        const char * mixer_ctl_name = "SLIM_0_RX Format";
+    int backend_idx = DEFAULT_CODEC_BACKEND;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+    backend_idx = platform_get_backend_index(snd_device);
+    ALOGV("%s bit width: %d, sample rate: %d backend_idx - %d",
+            __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);
+        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;
         }
 
         if (bit_width == 24) {
-                mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+            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);
     }
 
     /*
@@ -3103,10 +3281,9 @@
      * 24 bit playback - 192khz for sample rate range of 96khz to 192 khz
      * 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[backend_idx].sample_rate) {
             char *rate_str = NULL;
-            const char * mixer_ctl_name = "SLIM_0_RX SampleRate";
             struct  mixer_ctl *ctl;
 
             switch (sample_rate) {
@@ -3115,10 +3292,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:
@@ -3133,33 +3312,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;
+    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;
 
+    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
     if (voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
@@ -3179,51 +3371,63 @@
         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;
                 }
             }
         }
     }
-
-    // 16 bit playback on speakers is allowed through 48 khz backend only
-    if (16 == bit_width) {
-        sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-    }
-
-    //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  */
+    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: MCH session defaulting sample rate to %d",
-                 __func__, sample_rate);
+            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) &&
+            (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;
@@ -3234,20 +3438,27 @@
     return backend_change;
 }
 
-bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase)
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
+    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;
     }
 
@@ -3883,3 +4094,8 @@
 done:
     return ret;
 }
+
+int platform_get_wsa_mode (void *platform)
+{
+    return 0;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 41e2c55..4b90f8b 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -35,7 +35,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 | \
@@ -57,6 +61,7 @@
     SND_DEVICE_OUT_SPEAKER_EXTERNAL_2,
     SND_DEVICE_OUT_SPEAKER_REVERSE,
     SND_DEVICE_OUT_HEADPHONES,
+    SND_DEVICE_OUT_HEADPHONES_44_1,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
     SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2,
@@ -151,7 +156,16 @@
 
 };
 
-#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#define DEFAULT_OUTPUT_SAMPLING_RATE    48000
+#define OUTPUT_SAMPLING_RATE_44100      44100
+
+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
diff --git a/hal/platform_api.h b/hal/platform_api.h
index b2a0ccc..3a6dc02 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -26,6 +26,8 @@
 
 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);
@@ -38,6 +40,9 @@
 int platform_get_snd_device_acdb_id(snd_device_t snd_device);
 int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width);
 int platform_get_snd_device_bit_width(snd_device_t snd_device);
+int platform_set_native_support(bool codec_support);
+int platform_get_native_support();
+int platform_get_backend_index(snd_device_t snd_device);
 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);
@@ -57,7 +62,7 @@
 int platform_set_mic_mute(void *platform, bool state);
 int platform_get_sample_rate(void *platform, uint32_t *rate);
 int platform_set_device_mute(void *platform, bool state, char *dir);
-snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
+snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out);
 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device);
 int platform_set_hdmi_channels(void *platform, int channel_count);
 int platform_edid_get_max_channels(void *platform);
@@ -92,7 +97,8 @@
 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, struct audio_usecase *usecase);
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
+                   struct audio_usecase *usecase, snd_device_t snd_device);
 int platform_get_usecase_index(const char * usecase);
 int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
 void platform_set_echo_reference(void *platform, bool enable);
@@ -116,4 +122,5 @@
                                        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 *platform);
 #endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 6a35be5..50e19c6 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -44,6 +44,7 @@
     ROOT,
     ACDB,
     BITWIDTH,
+    NATIVESUPPORT,
     PCM_ID,
     BACKEND_NAME,
     INTERFACE_NAME,
@@ -54,6 +55,7 @@
 
 static void process_acdb_id(const XML_Char **attr);
 static void process_bit_width(const XML_Char **attr);
+static void process_native_support(const XML_Char **attr);
 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);
@@ -64,6 +66,7 @@
     [ROOT] = process_root,
     [ACDB] = process_acdb_id,
     [BITWIDTH] = process_bit_width,
+    [NATIVESUPPORT] = process_native_support,
     [PCM_ID] = process_pcm_id,
     [BACKEND_NAME] = process_backend_name,
     [INTERFACE_NAME] = process_interface_name,
@@ -281,7 +284,30 @@
                                               (char *)attr[5]);
     if (ret < 0) {
         ALOGE("%s: Audio Interface not set!", __func__);
+        goto done;
+    }
 
+done:
+    return;
+}
+
+static void process_native_support(const XML_Char **attr)
+{
+    int index;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found, no NATIVE_AUDIO_44.1 set!", __func__);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "codec_support") != 0) {
+        ALOGE("%s: NATIVE_AUDIO_44.1 in platform info xml has no codec_support set!",
+              __func__);
+        goto done;
+    }
+
+    if (platform_set_native_support(atoi((char *)attr[3])) < 0) {
+        ALOGE("%s: NATIVE_AUDIO_44 was not set!", __func__);
         goto done;
     }
 
@@ -344,6 +370,8 @@
         section = INTERFACE_NAME;
     } else if (strcmp(tag_name, "tz_names") == 0) {
         section = TZ_NAME;
+    } else if (strcmp(tag_name, "native_configs") == 0) {
+        section = NATIVESUPPORT;
     } else if (strcmp(tag_name, "device") == 0) {
         if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
             (section != INTERFACE_NAME) && (section != TZ_NAME)) {
@@ -362,6 +390,14 @@
 
         section_process_fn fn = section_table[PCM_ID];
         fn(attr);
+    } else if (strcmp(tag_name, "feature") == 0) {
+        if (section != NATIVESUPPORT) {
+            ALOGE("usecase tag only supported with NATIVESUPPORT section");
+            return;
+        }
+
+        section_process_fn fn = section_table[NATIVESUPPORT];
+        fn(attr);
     }
 
     return;
@@ -379,6 +415,8 @@
         section = ROOT;
     } else if (strcmp(tag_name, "interface_names") == 0) {
         section = ROOT;
+    } else if (strcmp(tag_name, "native_configs") == 0) {
+        section = ROOT;
     }
 }
 
diff --git a/hal/voice.c b/hal/voice.c
index c00df1a..527856f 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -56,6 +56,59 @@
     return session;
 }
 
+static bool voice_is_sidetone_device(snd_device_t out_device,
+            char *mixer_path)
+{
+    bool is_sidetone_dev;
+
+    switch (out_device) {
+    case SND_DEVICE_OUT_VOICE_HANDSET:
+        is_sidetone_dev = true;
+        strlcpy(mixer_path, "sidetone-handset", MIXER_PATH_MAX_LENGTH);
+        break;
+    case SND_DEVICE_OUT_VOICE_HEADPHONES:
+    case SND_DEVICE_OUT_VOICE_ANC_HEADSET:
+    case SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET:
+        is_sidetone_dev = true;
+        strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH);
+        break;
+    default:
+        is_sidetone_dev = false;
+        break;
+    }
+
+    return is_sidetone_dev;
+}
+
+void voice_set_sidetone(struct audio_device *adev,
+        snd_device_t out_snd_device, bool enable)
+{
+    char mixer_path[MIXER_PATH_MAX_LENGTH];
+    bool is_sidetone_dev;
+
+    ALOGD("%s: %s, out_snd_device: %d\n",
+          __func__, (enable ? "enable" : "disable"),
+          out_snd_device);
+
+    is_sidetone_dev = voice_is_sidetone_device(out_snd_device, mixer_path);
+
+    if (!is_sidetone_dev) {
+        ALOGD("%s: device %d does not support sidetone\n",
+              __func__, out_snd_device);
+        return;
+    }
+
+    ALOGD("%s: sidetone out device = %s\n",
+          __func__, mixer_path);
+
+    if (enable)
+        audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+    else
+        audio_route_reset_and_update_path(adev->audio_route, mixer_path);
+
+    return;
+}
+
 int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
 {
     int i, ret = 0;
@@ -70,10 +123,21 @@
         return -EINVAL;
     }
 
+    uc_info = get_usecase_from_list(adev, usecase_id);
+    if (uc_info == NULL) {
+        ALOGE("%s: Could not find the usecase (%d) in the list",
+              __func__, usecase_id);
+        return -EINVAL;
+    }
+
     session->state.current = CALL_INACTIVE;
     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))
+        voice_set_sidetone(adev, uc_info->out_snd_device, false);
+
     ret = platform_stop_voice_call(adev->platform, session->vsid);
 
     /* 1. Close the PCM devices */
@@ -86,13 +150,6 @@
         session->pcm_tx = NULL;
     }
 
-    uc_info = get_usecase_from_list(adev, usecase_id);
-    if (uc_info == NULL) {
-        ALOGE("%s: Could not find the usecase (%d) in the list",
-              __func__, usecase_id);
-        return -EINVAL;
-    }
-
     /* 2. Get and set stream specific mixer controls */
     disable_audio_route(adev, uc_info);
 
@@ -160,6 +217,17 @@
 
     voice_set_mic_mute(adev, adev->voice.mic_mute);
 
+    ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
+          __func__, adev->snd_card, pcm_dev_tx_id);
+    session->pcm_tx = pcm_open(adev->snd_card,
+                               pcm_dev_tx_id,
+                               PCM_IN, &voice_config);
+    if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
+        ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
+        ret = -EIO;
+        goto error_start_voice;
+    }
+
     ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
           __func__, adev->snd_card, pcm_dev_rx_id);
     session->pcm_rx = pcm_open(adev->snd_card,
@@ -171,18 +239,12 @@
         goto error_start_voice;
     }
 
-    ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
-          __func__, adev->snd_card, pcm_dev_tx_id);
-    session->pcm_tx = pcm_open(adev->snd_card,
-                               pcm_dev_tx_id,
-                               PCM_IN, &voice_config);
-    if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
-        ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
-        ret = -EIO;
-        goto error_start_voice;
-    }
-    pcm_start(session->pcm_rx);
     pcm_start(session->pcm_tx);
+    pcm_start(session->pcm_rx);
+
+    /* Enable sidetone only when no calls are already active */
+    if (!voice_is_call_state_active(adev))
+        voice_set_sidetone(adev, uc_info->out_snd_device, true);
 
     voice_set_volume(adev, adev->voice.volume);
 
diff --git a/hal/voice.h b/hal/voice.h
index 5a9cce1..139a8c8 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -95,4 +95,8 @@
                                             struct stream_in *in);
 void voice_update_devices_for_all_voice_usecases(struct audio_device *adev);
 snd_device_t voice_get_incall_rec_snd_device(snd_device_t in_snd_device);
+void voice_set_sidetone(struct audio_device *adev,
+                       snd_device_t out_snd_device,
+                       bool enable);
+bool voice_is_call_state_active(struct audio_device *adev);
 #endif //VOICE_H
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/bundle.c b/post_proc/bundle.c
index c09d2ad..b33f2d1 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -304,9 +304,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,
@@ -315,6 +312,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