hal: Changes to support true 44.1 Native playback

- add changes to support single BE mode on top of the
Double BE mode which is supported.

- support reading of version or mode from XML.

- add logic to switch between single and double BE
based on the mode in XML.

- define a new device for true native.

- add logic to read tasha codec version and allow
true native only for 2.0 version of codec

- enchance log msgs for better debugging.

Change-Id: I970487f16af32144ec26f967e8bfcb32d44d67a4
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 7cbed2d..c442aa7 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -506,7 +506,7 @@
 int b64decode(char *inp, int ilen, uint8_t* outp);
 int b64encode(uint8_t *inp, int ilen, char* outp);
 int read_line_from_file(const char *path, char *buf, size_t count);
-
+int audio_extn_utils_get_codec_version(const char *snd_card_name, int card_num, char *codec_version);
 #ifndef KPI_OPTIMIZE_ENABLED
 #define audio_extn_perf_lock_init() (0)
 #define audio_extn_perf_lock_acquire(handle, duration, opts, size) (0)
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index bb88916..ce49745 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -543,6 +543,20 @@
     app_type_cfg->bit_width = 16;
 }
 
+static bool audio_is_this_native_usecase(struct audio_usecase *uc)
+{
+    bool native_usecase = false;
+    struct stream_out *out = (struct stream_out*) uc->stream.out;
+
+    if (PCM_PLAYBACK == uc->type && out != NULL &&
+        NATIVE_AUDIO_MODE_INVALID != platform_get_native_support() &&
+        is_offload_usecase(uc->id) &&
+        (out->sample_rate == OUTPUT_SAMPLING_RATE_44100))
+        native_usecase = true;
+
+    return native_usecase;
+}
+
 int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
                                        struct audio_usecase *usecase)
 {
@@ -598,8 +612,7 @@
     if ((24 == usecase->stream.out->bit_width) &&
         (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
         usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
-    } else if ((snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
-        usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
+    } else if (!audio_is_this_native_usecase(usecase) ||
         (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
         usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
     }
@@ -621,8 +634,13 @@
         app_type_cfg[len++] = sample_rate * 4;
     else
         app_type_cfg[len++] = sample_rate;
+
     mixer_ctl_set_array(ctl, app_type_cfg, len);
     rc = 0;
+    ALOGI("%s:becf: adm: app_type %d, acdb_dev_id %d, sample_rate %d",
+          __func__,
+          platform_get_default_app_type_v2(adev->platform, usecase->type),
+          acdb_dev_id, sample_rate);
 exit_send_app_type_cfg:
     return rc;
 }
@@ -813,6 +831,31 @@
     return k;
 }
 
+
+int audio_extn_utils_get_codec_version(const char *snd_card_name,
+                            int card_num,
+                            char *codec_version)
+{
+    char procfs_path[50];
+    FILE *fp;
+
+    if (strstr(snd_card_name, "tasha")) {
+        snprintf(procfs_path, sizeof(procfs_path),
+                 "/proc/asound/card%d/codecs/tasha/version", card_num);
+        if ((fp = fopen(procfs_path, "r")) != NULL) {
+            fgets(codec_version, CODEC_VERSION_MAX_LENGTH, fp);
+            fclose(fp);
+        } else {
+            ALOGE("%s: ERROR. cannot open %s", __func__, procfs_path);
+            return -ENOENT;
+        }
+        ALOGD("%s: codec version %s", __func__, codec_version);
+    }
+
+    return 0;
+}
+
+
 #ifdef AUDIO_EXTERNAL_HDMI_ENABLED
 
 void get_default_compressed_channel_status(
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index e248f56..c088ffd 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -505,6 +505,7 @@
         return 0;
     }
 
+
     if (audio_extn_spkr_prot_is_enabled())
          audio_extn_spkr_prot_calib_cancel(adev);
     /* start usb playback thread */
@@ -546,6 +547,16 @@
         }
         audio_extn_dev_arbi_acquire(snd_device);
         audio_route_apply_and_update_path(adev->audio_route, device_name);
+
+        if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
+            !adev->native_playback_enabled &&
+            audio_is_true_native_stream_active(adev)) {
+            ALOGD("%s: %d: napb: enabling native mode in hardware",
+                  __func__, __LINE__);
+            audio_route_apply_and_update_path(adev->audio_route,
+                                              "true-native-mode");
+            adev->native_playback_enabled = true;
+        }
     }
     return 0;
 }
@@ -592,6 +603,14 @@
 
         if (snd_device == SND_DEVICE_OUT_HDMI)
             adev->is_channel_status_set = false;
+        else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
+                 adev->native_playback_enabled) {
+            ALOGD("%s: %d: napb: disabling native mode in hardware",
+                  __func__, __LINE__);
+            audio_route_reset_and_update_path(adev->audio_route,
+                                              "true-native-mode");
+            adev->native_playback_enabled = false;
+        }
 
         audio_extn_dev_arbi_release(snd_device);
         audio_extn_sound_trigger_update_device_status(snd_device,
@@ -633,6 +652,9 @@
      */
     bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
                          snd_device);
+
+    ALOGD("%s:becf: force routing %d", __func__, force_routing);
+
     backend_idx = platform_get_backend_index(snd_device);
     /* Disable all the usecases on the shared backend other than the
      * specified usecase.
@@ -646,17 +668,19 @@
         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));
+
+        ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
+              "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
+              __func__, i, 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->out_snd_device != snd_device || force_routing)  &&
                 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
                 usecase_backend_idx == backend_idx) {
-            ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
-                  use_case_table[usecase->id],
+            ALOGD("%s:becf: check_usecases (%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;
@@ -664,6 +688,9 @@
         }
     }
 
+    ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
+        num_uc_to_switch);
+
     if (num_uc_to_switch) {
         /* All streams have been de-routed. Disable the device */
 
@@ -690,6 +717,9 @@
             /* Update the out_snd_device only for the usecases that are enabled here */
             if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
                     usecase->out_snd_device = snd_device;
+                    ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
+                      use_case_table[usecase->id],
+                      platform_get_snd_device_name(usecase->out_snd_device));
                     enable_audio_route(adev, usecase);
             }
         }
@@ -834,6 +864,66 @@
     return NULL;
 }
 
+/*
+ * is a true native playback active
+ */
+bool audio_is_true_native_stream_active(struct audio_device *adev)
+{
+    bool active = false;
+    int i = 0;
+    struct listnode *node;
+
+    if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
+        ALOGV("%s:napb: not in true mode or non hdphones device",
+               __func__);
+        active = false;
+        goto exit;
+    }
+
+    list_for_each(node, &adev->usecase_list) {
+        struct audio_usecase *uc;
+        uc = node_to_item(node, struct audio_usecase, list);
+        struct stream_out *curr_out =
+            (struct stream_out*) uc->stream.out;
+
+        if (curr_out && PCM_PLAYBACK == uc->type) {
+            ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
+                  "(%d) device %s", __func__, i++, use_case_table[uc->id],
+                  uc->id, curr_out->sample_rate,
+                  curr_out->bit_width,
+                  platform_get_snd_device_name(uc->out_snd_device));
+
+            if (is_offload_usecase(uc->id) &&
+                (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
+                active = true;
+                ALOGD("%s:napb:native stream detected", __func__);
+            }
+        }
+    }
+exit:
+    return active;
+}
+
+
+static bool force_device_switch(struct audio_usecase *usecase)
+{
+    bool ret = false;
+    bool is_it_true_mode = false;
+
+    if (is_offload_usecase(usecase->id) &&
+        (usecase->stream.out) &&
+        (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
+        is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
+         if ((is_it_true_mode && !adev->native_playback_enabled) ||
+             (!is_it_true_mode && adev->native_playback_enabled)){
+            ret = true;
+            ALOGD("napb: time to toggle native mode");
+        }
+    }
+
+    return ret;
+}
+
 int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
 {
     snd_device_t out_snd_device = SND_DEVICE_NONE;
@@ -846,6 +936,8 @@
     struct listnode *node;
     int status = 0;
 
+    ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
+
     usecase = get_usecase_from_list(adev, uc_id);
     if (usecase == NULL) {
         ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
@@ -924,7 +1016,9 @@
 
     if (out_snd_device == usecase->out_snd_device &&
         in_snd_device == usecase->in_snd_device) {
-        return 0;
+
+        if (!force_device_switch(usecase))
+            return 0;
     }
 
     ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index fd19211..47c9070 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -358,6 +358,7 @@
     int perf_lock_handle;
     int perf_lock_opts[MAX_PERF_LOCK_OPTS];
     int perf_lock_opts_size;
+    bool native_playback_enabled;
 };
 
 int select_devices(struct audio_device *adev,
@@ -377,6 +378,8 @@
 
 bool is_offload_usecase(audio_usecase_t uc_id);
 
+bool audio_is_true_native_stream_active(struct audio_device *adev);
+
 int pcm_ioctl(struct pcm *pcm, int request, ...);
 
 int get_snd_card_state(struct audio_device *adev);
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 31233ad..6a30f88 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -201,12 +201,7 @@
     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};
+static native_audio_prop na_props = {0, 0, 0};
 
 struct platform_data {
     struct audio_device *adev;
@@ -250,6 +245,7 @@
     bool edid_valid;
     codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
     char ec_ref_mixer_path[64];
+    char codec_version[CODEC_VERSION_MAX_LENGTH];
 };
 
 static bool is_external_codec = false;
@@ -1127,8 +1123,6 @@
     }
 }
 
-
-
 static struct csd_data *open_csd_client()
 {
     struct csd_data *csd = calloc(1, sizeof(struct csd_data));
@@ -1637,7 +1631,7 @@
         }
 
         snd_card_name = mixer_get_name(adev->mixer);
-        ALOGV("%s: snd_card_name: %s", __func__, snd_card_name);
+        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
 
         my_data->hw_info = hw_info_init(snd_card_name);
         if (!my_data->hw_info) {
@@ -1877,21 +1871,26 @@
         strdup("SLIM_5_RX SampleRate");
 
 
-    if (platform_get_native_support()) {
+    ret = audio_extn_utils_get_codec_version(snd_card_name,
+                                             my_data->adev->snd_card,
+                                             my_data->codec_version);
 
-        if (strstr(snd_card_name, "tasha-snd-card") ||
-            strstr(snd_card_name, "tashalite-snd-card")) {
-            /* do nothing */
-        }
-        else {
-            platform_set_native_support(false);
+    if (NATIVE_AUDIO_MODE_INVALID != platform_get_native_support()) {
+        /*
+         * Native playback is enabled from the UI.
+         */
+        if(strstr(snd_card_name, "tasha")) {
+            if (strstr(my_data->codec_version, "WCD9335_1_0") ||
+                strstr(my_data->codec_version, "WCD9335_1_1")) {
+                ALOGD("%s:napb: TASHA 1.0 or 1.1 only SRC mode is supported",
+                      __func__);
+                platform_set_native_support(NATIVE_AUDIO_MODE_SRC);
+            }
+        } else {
+            platform_set_native_support(NATIVE_AUDIO_MODE_INVALID);
         }
     }
 
-    ALOGD("native: native audio: %s for sound card %s",
-        (platform_get_native_support() ? "enabled" : "disabled"),
-        snd_card_name);
-
     my_data->edid_info = NULL;
     return my_data;
 }
@@ -2184,26 +2183,31 @@
     }
     return backend_bit_width_table[snd_device];
 }
-
-int platform_set_native_support(bool codec_support)
+int platform_set_native_support(int na_mode)
 {
-    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);
+    if (NATIVE_AUDIO_MODE_SRC == na_mode || NATIVE_AUDIO_MODE_TRUE_44_1 == na_mode) {
+        na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled = true;
+        na_props.na_mode = na_mode;
+        ALOGD("%s:napb: native audio playback enabled in (%s) mode", __func__,
+              ((na_mode == NATIVE_AUDIO_MODE_SRC)?"SRC mode":"True 44.1 mode"));
+    } else {
+        na_props.platform_na_prop_enabled = false;
+        na_props.na_mode = NATIVE_AUDIO_MODE_INVALID;
+        ALOGD("%s:napb: native audio playback disabled", __func__);
+    }
+
     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;
+    int ret = NATIVE_AUDIO_MODE_INVALID;
+    if (na_props.platform_na_prop_enabled &&
+        na_props.ui_na_prop_enabled) {
+        ret = na_props.na_mode;
     }
-    ALOGV("%s: na_props.ui_na_prop_enabled: %d", __func__,
-           na_props.ui_na_prop_enabled);
+    ALOGV("%s:napb: ui Prop enabled(%d) version(%d)", __func__,
+          na_props.ui_na_prop_enabled, na_props.na_mode);
     return ret;
 }
 
@@ -2218,13 +2222,13 @@
         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);
+            ALOGV("%s:napb: 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);
+            ALOGV("%s:napb: native audio not supported: %d", __func__,
+                  na_props.platform_na_prop_enabled);
         }
     }
 }
@@ -2235,6 +2239,25 @@
     int ret = 0;
     struct audio_usecase *usecase;
     struct listnode *node;
+    int mode = NATIVE_AUDIO_MODE_INVALID;
+
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO_MODE,
+                             value, len);
+    if (ret >= 0) {
+        if (value && !strncmp(value, "src", sizeof("src")))
+            mode = NATIVE_AUDIO_MODE_SRC;
+        else if (value && !strncmp(value, "true", sizeof("true")))
+            mode = NATIVE_AUDIO_MODE_TRUE_44_1;
+        else {
+            mode = NATIVE_AUDIO_MODE_INVALID;
+            ALOGE("%s:napb:native_audio_mode in platform info xml,invalid mode string",
+                  __func__);
+        }
+        ALOGD("%s:napb updating mode (%d) from XML",__func__, mode);
+        platform_set_native_support(mode);
+    }
+
+
 
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO,
                              value, len);
@@ -2242,18 +2265,21 @@
         if (na_props.platform_na_prop_enabled) {
             if (!strncmp("true", value, sizeof("true"))) {
                 na_props.ui_na_prop_enabled = true;
-                ALOGD("%s: native audio feature enabled from UI",__func__);
+                ALOGD("%s:napb: native audio feature enabled from UI",
+                    __func__);
             }
             else {
                 na_props.ui_na_prop_enabled = false;
-                ALOGD("%s: native audio feature disabled from UI",__func__);
-
+                ALOGD("%s:napb: native audio feature disabled from UI",
+                      __func__);
             }
 
             str_parms_del(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO);
 
-            /* Iterate through the usecase list and trigger device switch for
-            all the appropriate usecases */
+            /*
+             * 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);
 
@@ -2261,21 +2287,48 @@
                     (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) {
-                         ALOGD("%s: triggering dynamic device switch for usecase(%d: %s)"
+                         ALOGD("%s:napb: triggering dynamic device switch for usecase(%d: %s)"
                                " stream(%p), device(%d)", __func__, usecase->id,
                                use_case_table[usecase->id], usecase->stream,
                                usecase->stream.out->devices);
                          select_devices(platform->adev, usecase->id);
                  }
             }
-        } else {
-              ALOGD("%s: native audio not supported: %d", __func__,
-                     na_props.platform_na_prop_enabled);
-        }
+        } else
+              ALOGD("%s:napb: native audio cannot be enabled from UI",
+                    __func__);
     }
     return ret;
 }
 
+int check_hdset_combo_device(struct audio_device *adev, snd_device_t snd_device)
+{
+    int ret = false;
+    struct listnode *node;
+    int i =0;
+
+    if (SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES == snd_device)
+        ret = true;
+    else {
+         list_for_each(node, &adev->usecase_list) {
+            struct audio_usecase *uc;
+            uc = node_to_item(node, struct audio_usecase, list);
+            ALOGD("%s: (%d) use case %s snd device %s",
+                __func__, i++, use_case_table[uc->id],
+                platform_get_snd_device_name(uc->out_snd_device));
+
+            if (SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES == uc->out_snd_device)
+                ret = true;
+        }
+    }
+    ALOGV("%s:napb: (%s) snd_device (%s)",
+          __func__, (ret == false ? "false":"true"),
+          platform_get_snd_device_name(snd_device));
+
+    return ret;
+}
+
+
 int platform_get_backend_index(snd_device_t snd_device)
 {
     int32_t port = DEFAULT_CODEC_BACKEND;
@@ -2287,10 +2340,10 @@
         else
             port = DEFAULT_CODEC_BACKEND;
     } else {
-        ALOGV("%s: Invalid device - %d ", __func__, snd_device);
+        ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
     }
 
-    ALOGV("%s: backend port - %d", __func__, port);
+    ALOGV("%s:napb: backend port - %d", __func__, port);
     return port;
 }
 
@@ -2599,6 +2652,7 @@
     snd_device_t snd_device = SND_DEVICE_NONE;
     audio_devices_t devices = out->devices;
     unsigned int sample_rate = out->sample_rate;
+    int na_mode = platform_get_native_support();
 #ifdef RECORD_PLAY_CONCURRENCY
     bool use_voip_out_devices = false;
     bool prop_rec_play_enabled = false;
@@ -2729,10 +2783,12 @@
     if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
         devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
         if (OUTPUT_SAMPLING_RATE_44100 == sample_rate &&
-            platform_get_native_support() &&
+            NATIVE_AUDIO_MODE_SRC == na_mode &&
             !audio_extn_get_anc_enabled()) {
+
             snd_device = SND_DEVICE_OUT_HEADPHONES_44_1;
-        }else if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
+
+        } else if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
             && audio_extn_get_anc_enabled()) {
 #ifdef RECORD_PLAY_CONCURRENCY
             if (use_voip_out_devices) {
@@ -4028,6 +4084,9 @@
     }
 }
 
+/*
+ * configures afe with bit width and Sample Rate
+ */
 int platform_set_codec_backend_cfg(struct audio_device* adev,
                          snd_device_t snd_device,
                          unsigned int bit_width, unsigned int sample_rate)
@@ -4035,16 +4094,15 @@
     int ret = 0;
     int backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
-    ALOGV("%s bit width: %d, sample rate: %d\n", __func__, bit_width, sample_rate);
-
     const char *snd_card_name = mixer_get_name(adev->mixer);
     int is_external_codec = platform_is_external_codec(snd_card_name);
-
+    int na_mode = platform_get_native_support();
 
 
     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);
+    ALOGI("%s:becf: afe: bitwidth %d, samplerate %d, backend_idx %d device (%s)",
+          __func__, bit_width, sample_rate, backend_idx,
+          platform_get_snd_device_name(snd_device));
 
     if (bit_width !=
         my_data->current_backend_cfg[backend_idx].bit_width) {
@@ -4059,8 +4117,9 @@
                         my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
         }
         if (!ctl) {
-            ALOGE("%s: Could not get ctl for mixer command - %s",
-                    __func__, my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+            ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
+                  __func__,
+                  my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
             return -EINVAL;
         }
 
@@ -4068,12 +4127,10 @@
                 mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else {
             mixer_ctl_set_enum_by_string(ctl, "S16_LE");
-            if (backend_idx != HEADPHONE_44_1_BACKEND)
-                sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         }
         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);
+        ALOGD("%s:becf: afe: %s mixer set to %d bit", __func__,
+              my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
     }
 
     /*
@@ -4087,7 +4144,7 @@
     // TODO: This has to be more dynamic based on policy file
 
     if ((sample_rate != my_data->current_backend_cfg[(int)backend_idx].sample_rate) &&
-        (is_external_codec) ) {
+            (is_external_codec)) {
             /* sample rate update is needed only for external codecs which
                support 24 bit playback*/
             char *rate_str = NULL;
@@ -4121,14 +4178,17 @@
 
             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__, my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl);
+
+            if (!ctl) {
+                ALOGE("%s:becf: afe: Could not get ctl to set the Sample Rate for mixer command - %s",
+                      __func__,
+                      my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl);
                 return -EINVAL;
             }
 
-            ALOGD("%s: %s set to %s", __func__,
-                my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl, rate_str);
+            ALOGD("%s:becf: afe: %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);
             my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
     }
@@ -4136,6 +4196,10 @@
     return ret;
 }
 
+/*
+ * goes through all the current usecases and picks the highest
+ * bitwidth & samplerate
+ */
 bool platform_check_codec_backend_cfg(struct audio_device* adev,
                                    struct audio_usecase* usecase,
                                    snd_device_t snd_device,
@@ -4151,21 +4215,24 @@
     int backend_idx = DEFAULT_CODEC_BACKEND;
     int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
+    int na_mode = platform_get_native_support();
 
     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);
+    ALOGI("%s:becf: afe: 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 i.e. 16b/48K, only applicable to
     // default backend
     // force routing is not required here, caller will do it anyway
     if ((voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
         backend_idx == DEFAULT_CODEC_BACKEND) {
-        ALOGW("%s:Use default bw and sr for voice/voip calls ",__func__);
+        ALOGW("%s:becf: afe:Use default bw and sr for voice/voip calls ",
+              __func__);
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     } else {
@@ -4176,22 +4243,24 @@
          * current backend sample rate and/or bit width, then, we set the
          * backend re-configuration flag.
          *
-         * Exception: 16 bit playbacks is allowed through 16 bit/48 khz backend only
+         * Exception: 16 bit playbacks is allowed through 16 bit/48/44.1 khz backend only
          */
+        int i =0;
         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 &&
-                usecase != curr_usecase) {
-                struct stream_out *out =
-                           (struct stream_out*) curr_usecase->stream.out;
-                usecase_backend_idx = platform_get_backend_index(curr_usecase->out_snd_device);
+            struct audio_usecase *uc;
+            uc = node_to_item(node, struct audio_usecase, list);
+            struct stream_out *out = (struct stream_out*) uc->stream.out;
+            if (uc->type == PCM_PLAYBACK && out && usecase != uc) {
+                usecase_backend_idx =
+                    platform_get_backend_index(uc->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);
+                ALOGD("%s:napb: (%d) - (%s)id (%d) sr %d bw "
+                      "(%d) device %s", __func__, i++, use_case_table[uc->id],
+                      uc->id, out->sample_rate,
+                      out->bit_width,
+                      platform_get_snd_device_name(uc->out_snd_device));
+
+                if (usecase_backend_idx == backend_idx) {
                         if (bit_width < out->bit_width)
                             bit_width = out->bit_width;
                         if (sample_rate < out->sample_rate)
@@ -4202,31 +4271,62 @@
             }
         }
     }
-    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);
-        }
 
-        // 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);
+    if (audio_is_true_native_stream_active(adev)) {
+        if (check_hdset_combo_device(adev, snd_device)) {
+        /*
+         * In true native mode Tasha has a limitation that one port at 44.1 khz
+         * cannot drive both spkr and hdset, to simiplify the solution lets
+         * move the AFE to 48khzwhen a ring tone selects combo device.
+         */
             sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+            bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+            ALOGD("%s:becf: afe: port has to run at 48k for a combo device",
+                  __func__);
+        } else {
+        /*
+         * in single BE mode, if native audio playback
+         * is active then it will take priority
+         */
+            sample_rate = OUTPUT_SAMPLING_RATE_44100;
+            ALOGD("%s:becf: afe: napb active set rate to 44.1 khz",
+                  __func__);
         }
     }
 
+
+    /*
+     * 24 bit playback on speakers is allowed through 48
+     * khz backend only
+     */
+    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;
+        ALOGD("%s:becf: afe: 24 bit playback on speakers"
+              "Configure afe to default Sample Rate(48k)", __func__);
+    }
+
+    /*
+     * native playback is not enabled.Configure afe to default Sample Rate(48k)
+     */
+    if (NATIVE_AUDIO_MODE_INVALID == na_mode &&
+            OUTPUT_SAMPLING_RATE_44100 == sample_rate) {
+        sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        ALOGD("%s:becf: afe: napb not active - set (48k) default rate",
+              __func__);
+    }
+
     /*
      * Sample rate greater than 48K is only supported by external codecs on
      * specific devices e.g. Headphones, reset the sample rate to
      * default value if not external codec.
      */
-    if (!is_external_codec)
+    if (!is_external_codec) {
+        ALOGD("%s:becf: afe: For internal codec only 48 is supported \
+              Configure afe to default Sample Rate(48k)", __func__);
         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,"");
@@ -4243,9 +4343,9 @@
          }
     }
 
-
-    ALOGI("%s Codec selected backend: %d updated bit width: %d and sample rate: %d",
-               __func__, backend_idx, bit_width, sample_rate);
+    ALOGI("%s:becf: afe: 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 != my_data->current_backend_cfg[backend_idx].bit_width) ||
@@ -4253,8 +4353,9 @@
         *new_bit_width = bit_width;
         *new_sample_rate = sample_rate;
         backend_change = true;
-        ALOGI("%s Codec backend needs to be updated. new bit width: %d new sample rate: %d",
-               __func__, *new_bit_width, *new_sample_rate);
+        ALOGI("%s:becf: afe: Codec backend needs to be updated. new bit width: %d new sample rate: %d",
+              __func__,
+             *new_bit_width, *new_sample_rate);
     }
 
     return backend_change;
@@ -4268,15 +4369,15 @@
     int backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
 
-    ALOGV("%s: usecase = %d", __func__, usecase->id );
-
     backend_idx = platform_get_backend_index(snd_device);
 
     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);
+    ALOGI("%s:becf: afe: bitwidth %d, samplerate %d"
+          ", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
+          new_sample_rate, backend_idx, usecase->id,
+          platform_get_snd_device_name(snd_device));
     if (platform_check_codec_backend_cfg(adev, usecase, snd_device,
                                       &new_bit_width, &new_sample_rate)) {
         platform_set_codec_backend_cfg(adev, snd_device,
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 39c154b..6996246 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -195,11 +195,14 @@
     MAX_CODEC_BACKENDS
 };
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
+#define AUDIO_PARAMETER_KEY_NATIVE_AUDIO_MODE "native_audio_mode"
 
 #define ALL_SESSION_VSID                0xFFFFFFFF
 #define DEFAULT_MUTE_RAMP_DURATION_MS   20
 #define DEFAULT_VOLUME_RAMP_DURATION_MS 20
 #define MIXER_PATH_MAX_LENGTH 100
+#define SND_CARD_MAX_LENGTH 100
+#define CODEC_VERSION_MAX_LENGTH 100
 
 #define MAX_VOL_INDEX 5
 #define MIN_VOL_INDEX 0
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 8c17895..8ad9922 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -198,11 +198,7 @@
     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};
+static native_audio_prop na_props = {0, 0, 0};
 typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
 
 struct platform_data {
@@ -246,6 +242,7 @@
     bool edid_valid;
     char ec_ref_mixer_path[64];
     codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
+    char codec_version[CODEC_VERSION_MAX_LENGTH];
 };
 
 static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -1273,7 +1270,7 @@
     char value[PROPERTY_VALUE_MAX];
     struct platform_data *my_data = NULL;
     int retry_num = 0, snd_card_num = 0, key = 0;
-    const char *snd_card_name = NULL;
+    const char *snd_card_name = NULL, *snd_card_name_t = NULL;
     char *cvd_version = NULL;
     char *snd_internal_name = NULL;
     char *tmp = NULL;
@@ -1310,7 +1307,7 @@
             free(my_data);
             return NULL;
         }
-        ALOGV("%s: snd_card_name: %s", __func__, snd_card_name);
+        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
 
         my_data->hw_info = hw_info_init(snd_card_name);
         if (!my_data->hw_info) {
@@ -1334,8 +1331,9 @@
                  * done to preserve backward compatibility but not mandatory as
                  * long as the mixer files are named as per above assumption.
                 */
+                snd_card_name_t = strdup(snd_card_name);
+                snd_internal_name = strtok_r(snd_card_name_t, "-", &tmp);
 
-                snd_internal_name = strtok_r(snd_card_name, "-", &tmp);
                 if (snd_internal_name != NULL)
                     snd_internal_name = strtok_r(NULL, "-", &tmp);
 
@@ -1372,6 +1370,7 @@
                        __func__);
                 free(my_data);
                 free(snd_card_name);
+                free(snd_card_name_t);
                 return NULL;
             }
             adev->snd_card = snd_card_num;
@@ -1387,6 +1386,8 @@
         free(my_data);
         if (snd_card_name)
             free(snd_card_name);
+        if (snd_card_name_t)
+            free(snd_card_name_t);
         return NULL;
     }
 
@@ -1584,8 +1585,29 @@
     my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].samplerate_mixer_ctl =
         strdup("SLIM_5_RX SampleRate");
 
+    ret = audio_extn_utils_get_codec_version(snd_card_name,
+                                             my_data->adev->snd_card,
+                                             my_data->codec_version);
+
+    if (NATIVE_AUDIO_MODE_INVALID != platform_get_native_support()) {
+        /*
+         * Native playback is enabled from the UI.
+         */
+        if(strstr(snd_card_name, "tasha")) {
+            if (strstr(my_data->codec_version, "WCD9335_1_0") ||
+                strstr(my_data->codec_version, "WCD9335_1_1")) {
+                ALOGD("%s:napb: TASHA 1.0 or 1.1 only SRC mode is supported",
+                      __func__);
+                platform_set_native_support(NATIVE_AUDIO_MODE_SRC);
+            }
+        } else {
+            platform_set_native_support(NATIVE_AUDIO_MODE_INVALID);
+        }
+    }
+
     my_data->edid_info = NULL;
     free(snd_card_name);
+    free(snd_card_name_t);
     return my_data;
 }
 
@@ -1870,26 +1892,32 @@
     return backend_bit_width_table[snd_device];
 }
 
-int platform_set_native_support(bool codec_support)
+int platform_set_native_support(int na_mode)
 {
-    int ret = 0;
-    na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled
-        = codec_support;
-    ALOGD("%s: na_props.platform_na_prop_enabled: %d", __func__,
-           na_props.platform_na_prop_enabled);
-    return ret;
+    if (NATIVE_AUDIO_MODE_SRC == na_mode || NATIVE_AUDIO_MODE_TRUE_44_1 == na_mode) {
+        na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled = true;
+        na_props.na_mode = na_mode;
+        ALOGD("%s:napb: native audio playback enabled in (%s) mode", __func__,
+              ((na_mode == NATIVE_AUDIO_MODE_SRC)?"SRC mode":"True 44.1 mode"));
+    }
+    else {
+        na_props.platform_na_prop_enabled = false;
+        na_props.na_mode = NATIVE_AUDIO_MODE_INVALID;
+        ALOGD("%s:napb: native audio playback disabled", __func__);
+    }
+
+    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;
+    int ret = NATIVE_AUDIO_MODE_INVALID;
+    if (na_props.platform_na_prop_enabled &&
+        na_props.ui_na_prop_enabled) {
+        ret = na_props.na_mode;
     }
-    ALOGV("%s: na_props.ui_na_prop_enabled: %d", __func__,
-           na_props.ui_na_prop_enabled);
+    ALOGV("%s:napb: ui Prop enabled(%d) version(%d)", __func__,
+           na_props.ui_na_prop_enabled, na_props.na_mode);
     return ret;
 }
 
@@ -1904,13 +1932,13 @@
         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);
+            ALOGV("%s:napb: 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);
+            ALOGV("%s:napb: native audio not supported: %d", __func__,
+                  na_props.platform_na_prop_enabled);
         }
     }
 }
@@ -1921,6 +1949,25 @@
     int ret = 0;
     struct audio_usecase *usecase;
     struct listnode *node;
+    int mode = NATIVE_AUDIO_MODE_INVALID;
+
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO_MODE,
+                             value, len);
+    if (ret >= 0) {
+        if (value && !strncmp(value, "src", sizeof("src")))
+            mode = NATIVE_AUDIO_MODE_SRC;
+        else if (value && !strncmp(value, "true", sizeof("true")))
+            mode = NATIVE_AUDIO_MODE_TRUE_44_1;
+        else {
+            mode = NATIVE_AUDIO_MODE_INVALID;
+            ALOGE("%s:napb:native_audio_mode in platform info xml,invalid mode string",
+                  __func__);
+        }
+        ALOGD("%s:napb updating mode (%d) from XML",__func__, mode);
+        platform_set_native_support(mode);
+    }
+
+
 
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO,
                              value, len);
@@ -1928,12 +1975,12 @@
         if (na_props.platform_na_prop_enabled) {
             if (!strncmp("true", value, sizeof("true"))) {
                 na_props.ui_na_prop_enabled = true;
-                ALOGD("%s: native audio feature enabled from UI",__func__);
-            }
-            else {
+                ALOGD("%s:napb: native audio feature enabled from UI",
+                    __func__);
+            } else {
                 na_props.ui_na_prop_enabled = false;
-                ALOGD("%s: native audio feature disabled from UI",__func__);
-
+                ALOGD("%s:napb: native audio feature disabled from UI",
+                      __func__);
             }
 
             str_parms_del(parms, AUDIO_PARAMETER_KEY_NATIVE_AUDIO);
@@ -1949,21 +1996,46 @@
                     (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) {
-                         ALOGD("%s: triggering dynamic device switch for usecase(%d: %s)"
+                         ALOGD("%s:napb: triggering dynamic device switch for usecase(%d: %s)"
                                " stream(%p), device(%d)", __func__, usecase->id,
                                use_case_table[usecase->id], usecase->stream,
                                usecase->stream.out->devices);
                          select_devices(platform->adev, usecase->id);
                  }
             }
-        } else {
-              ALOGD("%s: native audio not supported: %d", __func__,
-                     na_props.platform_na_prop_enabled);
-        }
+        } else
+              ALOGD("%s:napb: native audio cannot be enabled from UI",
+                    __func__);
     }
     return ret;
 }
 
+int check_hdset_combo_device(struct audio_device *adev, snd_device_t snd_device)
+{
+    int ret = false;
+    struct listnode *node;
+    int i =0;
+
+    if (SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES == snd_device)
+        ret = true;
+    else {
+         list_for_each(node, &adev->usecase_list) {
+            struct audio_usecase *uc;
+            uc = node_to_item(node, struct audio_usecase, list);
+            ALOGD("%s: (%d) use case %s snd device %s",
+                __func__, i++, use_case_table[uc->id],
+                platform_get_snd_device_name(uc->out_snd_device));
+
+            if (SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES == uc->out_snd_device)
+                ret = true;
+        }
+    }
+    ALOGV("%s:napb: (%s) snd_device (%s)",
+          __func__, (ret == false ? "false":"true"),
+          platform_get_snd_device_name(snd_device));
+
+    return ret;
+}
 int platform_get_backend_index(snd_device_t snd_device)
 {
     int32_t port = DEFAULT_CODEC_BACKEND;
@@ -1975,10 +2047,10 @@
         else
             port = DEFAULT_CODEC_BACKEND;
     } else {
-        ALOGV("%s: Invalid device - %d ", __func__, snd_device);
+        ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
     }
 
-    ALOGV("%s: backend port - %d", __func__, port);
+    ALOGV("%s:napb: backend port - %d", __func__, port);
     return port;
 }
 
@@ -2291,6 +2363,7 @@
     snd_device_t snd_device = SND_DEVICE_NONE;
     audio_devices_t devices = out->devices;
     unsigned int sample_rate = out->sample_rate;
+    int na_mode = platform_get_native_support();
 
     audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
                                 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
@@ -2412,11 +2485,11 @@
                 snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET;
             else
                 snd_device = SND_DEVICE_OUT_ANC_HEADSET;
-        } else if (platform_get_native_support() &&
-                    OUTPUT_SAMPLING_RATE_44100 == sample_rate)
+        } else if (NATIVE_AUDIO_MODE_SRC == na_mode &&
+                   OUTPUT_SAMPLING_RATE_44100 == sample_rate) {
                 snd_device = SND_DEVICE_OUT_HEADPHONES_44_1;
-          else
-                snd_device = SND_DEVICE_OUT_HEADPHONES;
+        } else
+            snd_device = SND_DEVICE_OUT_HEADPHONES;
     } else if (devices & AUDIO_DEVICE_OUT_LINE) {
         snd_device = SND_DEVICE_OUT_LINE;
     } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
@@ -3591,6 +3664,9 @@
     return OFFLOAD_USE_SMALL_BUFFER;
 }
 
+/*
+ * configures afe with bit width and Sample Rate
+ */
 int platform_set_codec_backend_cfg(struct audio_device* adev,
                          snd_device_t snd_device,
                          unsigned int bit_width, unsigned int sample_rate)
@@ -3600,8 +3676,10 @@
     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);
+
+    ALOGI("%s:becf: afe: bitwidth %d, samplerate %d"
+          ", backend_idx %d device (%s)", __func__,  bit_width, sample_rate, backend_idx,
+          platform_get_snd_device_name(snd_device));
 
     if (bit_width !=
         my_data->current_backend_cfg[backend_idx].bit_width) {
@@ -3610,8 +3688,9 @@
         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__, my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+            ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
+                  __func__,
+                  my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl);
             return -EINVAL;
         }
 
@@ -3619,12 +3698,10 @@
             mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else {
             mixer_ctl_set_enum_by_string(ctl, "S16_LE");
-            if (backend_idx != HEADPHONE_44_1_BACKEND)
-                sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         }
         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);
+        ALOGD("%s:becf: afe: %s mixer set to %d bit", __func__,
+              my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
     }
 
     /*
@@ -3669,13 +3746,14 @@
             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__, my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl);
+                ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
+                      __func__,
+                      my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl);
                 return -EINVAL;
             }
 
-            ALOGD("%s: %s set to %s", __func__,
-                my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl, rate_str);
+            ALOGD("%s:becf: afe: %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);
             my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
     }
@@ -3683,6 +3761,10 @@
     return ret;
 }
 
+/*
+ * goes through all the current usecases and picks the highest
+ * bitwidth & samplerate
+ */
 bool platform_check_codec_backend_cfg(struct audio_device* adev,
                                    struct audio_usecase* usecase,
                                    snd_device_t snd_device,
@@ -3697,21 +3779,25 @@
     int backend_idx = DEFAULT_CODEC_BACKEND;
     int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
+    int na_mode = platform_get_native_support();
 
     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);
+    ALOGI("%s:becf: afe: bitwidth %d, samplerate %d"
+          ", backend_idx %d usecase = %d device (%s)", __func__, bit_width,
+          sample_rate, backend_idx, usecase->id,
+          platform_get_snd_device_name(snd_device));
 
     // For voice calls use default configuration i.e. 16b/48K, only applicable to
     // default backend
     // force routing is not required here, caller will do it anyway
     if ((voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
         backend_idx == DEFAULT_CODEC_BACKEND) {
-        ALOGW("%s:Use default bw and sr for voice/voip calls ",__func__);
+        ALOGW("%s:becf: afe:Use default bw and sr for voice/voip calls ",
+              __func__);
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     } else {
@@ -3722,22 +3808,24 @@
          * current backend sample rate and/or bit width, then, we set the
          * backend re-configuration flag.
          *
-         * Exception: 16 bit playbacks is allowed through 16 bit/48 khz backend only
+         * Exception: 16 bit playbacks is allowed through 16 bit/48/44.1 khz backend only
          */
+        int i =0;
         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 &&
-                usecase != curr_usecase) {
-                struct stream_out *out =
-                           (struct stream_out*) curr_usecase->stream.out;
-                usecase_backend_idx = platform_get_backend_index(curr_usecase->out_snd_device);
+            struct audio_usecase *uc;
+            uc = node_to_item(node, struct audio_usecase, list);
+            struct stream_out *out = (struct stream_out*) uc->stream.out;
+            if (uc->type == PCM_PLAYBACK && out && usecase != uc) {
+                usecase_backend_idx =
+                    platform_get_backend_index(uc->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);
+                ALOGD("%s:napb: (%d) - (%s)id (%d) sr %d bw "
+                      "(%d) device %s", __func__, i++, use_case_table[uc->id],
+                      uc->id, out->sample_rate,
+                      out->bit_width,
+                      platform_get_snd_device_name(uc->out_snd_device));
+
+                if (usecase_backend_idx == backend_idx) {
                         if (bit_width < out->bit_width)
                             bit_width = out->bit_width;
                         if (sample_rate < out->sample_rate)
@@ -3749,24 +3837,52 @@
         }
     }
 
-    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) {
+    if (audio_is_true_native_stream_active(adev)) {
+        if (check_hdset_combo_device(adev, snd_device)) {
+        /*
+         * In true native mode Tasha has a limitation that one port at 44.1 khz
+         * cannot drive both spkr and hdset, to simiplify the solution lets
+         * move the AFE to 48khzwhen a ring tone selects combo device.
+         */
             sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
-            ALOGD("%s: resetting sample_rate back to default, "
-                   "backend_idx: %d", __func__, backend_idx);
-        }
-        // 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;
+            bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+            ALOGD("%s:becf: afe: port has to run at 48k for a combo device",
+                  __func__);
+        } else {
+        /*
+         * in single BE mode, if native audio playback
+         * is active then it will take priority
+         */
+            sample_rate = OUTPUT_SAMPLING_RATE_44100;
+            ALOGD("%s:becf: afe: true napb active set rate to 44.1 khz",
+                  __func__);
         }
     }
-    ALOGI("%s Codec selected backend: %d updated bit width: %d and sample rate: %d",
-               __func__, backend_idx, bit_width, sample_rate);
+
+    /*
+     * 24 bit playback on speakers is allowed through 48
+     * khz backend only
+     */
+    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;
+        ALOGD("%s:becf: afe: 24 bit playback on speakers"
+              "Configure afe to default Sample Rate(48k)", __func__);
+    }
+
+    /*
+     * native playback is not enabled.Configure afe to default Sample Rate(48k)
+     */
+    if (NATIVE_AUDIO_MODE_INVALID == na_mode &&
+            OUTPUT_SAMPLING_RATE_44100 == sample_rate) {
+        sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        ALOGD("%s:becf: afe: napb not active - set (48k) default rate",
+              __func__);
+    }
+
+    ALOGI("%s:becf: afe: 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 != my_data->current_backend_cfg[backend_idx].bit_width) ||
@@ -3774,8 +3890,8 @@
         *new_bit_width = bit_width;
         *new_sample_rate = sample_rate;
         backend_change = true;
-        ALOGI("%s Codec backend needs to be updated. new bit width: %d new sample rate: %d",
-               __func__, *new_bit_width, *new_sample_rate);
+        ALOGI("%s:becf: afe: Codec backend needs to be updated. new bit width: %d new sample rate: %d",
+              __func__, *new_bit_width, *new_sample_rate);
     }
 
     return backend_change;
@@ -3789,15 +3905,16 @@
     int backend_idx = DEFAULT_CODEC_BACKEND;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
 
-    ALOGV("%s: usecase = %d", __func__, usecase->id );
-
     backend_idx = platform_get_backend_index(snd_device);
 
     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);
+    ALOGI("%s:becf: afe: bitwidth %d, samplerate %d"
+          ", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
+          new_sample_rate, backend_idx, usecase->id,
+          platform_get_snd_device_name(snd_device));
+
     if (platform_check_codec_backend_cfg(adev, usecase, snd_device,
                                       &new_bit_width, &new_sample_rate)) {
         platform_set_codec_backend_cfg(adev, snd_device,
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9045562..896751b 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -186,11 +186,13 @@
 };
 
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
+#define AUDIO_PARAMETER_KEY_NATIVE_AUDIO_MODE "native_audio_mode"
 
 #define ALL_SESSION_VSID                0xFFFFFFFF
 #define DEFAULT_MUTE_RAMP_DURATION_MS   20
 #define DEFAULT_VOLUME_RAMP_DURATION_MS 20
 #define MIXER_PATH_MAX_LENGTH 100
+#define CODEC_VERSION_MAX_LENGTH 100
 
 #define MAX_VOL_INDEX 5
 #define MIN_VOL_INDEX 0
diff --git a/hal/platform_api.h b/hal/platform_api.h
index e5ec2d6..44f7d14 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -24,6 +24,18 @@
 #define CODEC_BACKEND_DEFAULT_BIT_WIDTH 16
 #define CODEC_BACKEND_DEFAULT_SAMPLE_RATE 48000
 
+enum {
+    NATIVE_AUDIO_MODE_SRC = 1,
+    NATIVE_AUDIO_MODE_TRUE_44_1,
+    NATIVE_AUDIO_MODE_INVALID
+};
+
+typedef struct {
+    bool platform_na_prop_enabled;
+    bool ui_na_prop_enabled;
+    int na_mode;
+} native_audio_prop;
+
 void *platform_init(struct audio_device *adev);
 void platform_deinit(void *platform);
 const char *platform_get_snd_device_name(snd_device_t snd_device);
@@ -40,7 +52,7 @@
 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_set_native_support(int na_mode);
 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,
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 6514cb3..92cc930 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -45,7 +45,6 @@
     ROOT,
     ACDB,
     BITWIDTH,
-    NATIVESUPPORT,
     PCM_ID,
     BACKEND_NAME,
     INTERFACE_NAME,
@@ -57,7 +56,6 @@
 
 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);
@@ -69,7 +67,6 @@
     [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,
@@ -307,31 +304,6 @@
 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;
-    }
-
-done:
-    return;
-}
-
 static void process_tz_name(const XML_Char **attr)
 {
     int ret, index;
@@ -407,8 +379,6 @@
         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)) {
@@ -427,14 +397,6 @@
 
         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);
     } else if (strcmp(tag_name, "param") == 0) {
         if (section != CONFIG_PARAMS) {
             ALOGE("param tag only supported with CONFIG_PARAMS section");
@@ -463,8 +425,6 @@
         platform_set_parameters(my_data.platform, my_data.kvpairs);
     } else if (strcmp(tag_name, "interface_names") == 0) {
         section = ROOT;
-    } else if (strcmp(tag_name, "native_configs") == 0) {
-        section = ROOT;
     }
 }