hal : native DSD concurrency support over headphone.

 -Enable ASRC mode for headphone backend if headphone 44.1 or
  native DSD backend is active.
 -Disable headphone backend and reopen it with ASRC mode for upcoming
  use case over headphone 44.1 or native DSD backend

Change-Id: Ic8fb0ab9f254d3472fda49dbb824f622d518a451
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 70909f5..b617407 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -621,6 +621,36 @@
     return 0;
 }
 
+/*
+ * Enable ASRC mode if native or DSD stream is active.
+ */
+static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
+{
+    if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
+       !adev->asrc_mode_enabled) {
+        struct listnode *node = NULL;
+        struct audio_usecase *uc = NULL;
+        struct stream_out *curr_out = NULL;
+
+        list_for_each(node, &adev->usecase_list) {
+            uc = node_to_item(node, struct audio_usecase, list);
+            curr_out = (struct stream_out*) uc->stream.out;
+
+            if (curr_out && PCM_PLAYBACK == uc->type) {
+                if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
+                      (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
+                    ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
+                          __func__);
+                    audio_route_apply_and_update_path(adev->audio_route,
+                                                  "asrc-mode");
+                    adev->asrc_mode_enabled = true;
+                    break;
+                }
+            }
+        }
+    }
+}
+
 int pcm_ioctl(struct pcm *pcm, int request, ...)
 {
     va_list ap;
@@ -772,7 +802,8 @@
             audio_route_apply_and_update_path(adev->audio_route,
                                               "true-native-mode");
             adev->native_playback_enabled = true;
-        }
+        } else
+            audio_check_and_set_asrc_mode(adev, snd_device);
     }
     return 0;
 }
@@ -829,6 +860,11 @@
             audio_route_reset_and_update_path(adev->audio_route,
                                               "true-native-mode");
             adev->native_playback_enabled = false;
+        } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
+                 adev->asrc_mode_enabled) {
+            ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
+            audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
+            adev->asrc_mode_enabled = false;
         }
 
         audio_extn_dev_arbi_release(snd_device);
@@ -900,7 +936,9 @@
             ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
              (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
              (force_restart_session)) &&
-            platform_check_backends_match(snd_device, usecase->out_snd_device)) {
+            (platform_check_backends_match(snd_device, usecase->out_snd_device)||
+             (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
+              platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
                 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));
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 1b5c6c9..197807c 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -389,6 +389,7 @@
     int perf_lock_opts[MAX_PERF_LOCK_OPTS];
     int perf_lock_opts_size;
     bool native_playback_enabled;
+    bool asrc_mode_enabled;
 };
 
 int select_devices(struct audio_device *adev,
@@ -411,6 +412,7 @@
 bool audio_is_true_native_stream_active(struct audio_device *adev);
 
 bool audio_is_dsd_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 8894b2f..9c6cc6f 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5413,3 +5413,14 @@
 {
     return false;
 }
+
+bool platform_check_codec_asrc_support(void *platform __unused)
+{
+    return false;
+}
+
+bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device __unused,
+                                                  snd_device_t cuurent_snd_device __unused)
+{
+    return false;
+}
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 1b47e7d..e5d42bd 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1266,4 +1266,15 @@
 int platform_get_backend_index(snd_device_t snd_device __unused);
 {
     return 0;
-}
\ No newline at end of file
+}
+
+bool platform_check_codec_asrc_support(void *platform __unused)
+{
+    return false;
+}
+
+bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device __unused,
+                                                  snd_device_t cuurent_snd_device __unused)
+{
+    return false;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 9c85d10..f12114a 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -248,6 +248,7 @@
     int source_mic_type;
     int max_mic_count;
     bool is_dsd_supported;
+    bool is_asrc_supported;
 };
 
 static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -1759,6 +1760,7 @@
     if(strstr(snd_card_name, "tavil")) {
         ALOGD("%s:DSD playback is supported", __func__);
         my_data->is_dsd_supported = true;
+        my_data->is_asrc_supported = true;
         platform_set_native_support(NATIVE_AUDIO_MODE_MULTIPLE_44_1);
     }
 
@@ -1924,6 +1926,32 @@
     return result;
 }
 
+bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device,
+                                                  snd_device_t cuurent_snd_device)
+{
+    bool result = false;
+
+    ALOGV("%s: current snd device = %s, new snd device = %s", __func__,
+                platform_get_snd_device_name(cuurent_snd_device),
+                platform_get_snd_device_name(new_snd_device));
+
+    if ((new_snd_device < SND_DEVICE_MIN) || (new_snd_device >= SND_DEVICE_OUT_END) ||
+            (cuurent_snd_device < SND_DEVICE_MIN) || (cuurent_snd_device >= SND_DEVICE_OUT_END)) {
+        ALOGE("%s: Invalid snd_device",__func__);
+        return false;
+    }
+
+    if (cuurent_snd_device == SND_DEVICE_OUT_HEADPHONES &&
+            (new_snd_device == SND_DEVICE_OUT_HEADPHONES_44_1 ||
+             new_snd_device == SND_DEVICE_OUT_HEADPHONES_DSD)) {
+        result = true;
+    }
+
+    ALOGV("%s: Need to disable current backend %s, %d",
+          __func__, platform_get_snd_device_name(cuurent_snd_device), result);
+    return result;
+}
+
 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
 {
     int device_id;
@@ -2131,6 +2159,12 @@
     return my_data->is_dsd_supported;
 }
 
+bool platform_check_codec_asrc_support(void *platform)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    return my_data->is_asrc_supported;
+}
+
 int platform_get_native_support()
 {
     int ret = NATIVE_AUDIO_MODE_INVALID;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 60e46f1..625f4eb 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -152,6 +152,8 @@
                           bool enable,
                           char * str);
 bool platform_supports_true_32bit();
+bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device, snd_device_t cuurent_snd_device);
 bool platform_check_codec_dsd_support(void *platform);
+bool platform_check_codec_asrc_support(void *platform);
 int platform_get_backend_index(snd_device_t snd_device);
 #endif // AUDIO_PLATFORM_API_H