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_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__,