hal: update combo device handling

If the wired headset/headphone/line devices are handled by
a different backend than speaker/earpiece devices, the combo
devices such as speaker+headphones can be split into individual
devices and enabled/disabled independently.

Conflicts:
	hal/msm8916/platform.c
	hal/msm8974/platform.c

Change-Id: I30e90f398ef204d106b5d8dac8fba166583bdbc8
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index d10bc18..5bd6651 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -483,6 +483,8 @@
 int enable_snd_device(struct audio_device *adev,
                       snd_device_t snd_device)
 {
+    int i, num_devices = 0;
+    snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
     char device_name[DEVICE_NAME_MAX_SIZE] = {0};
 
     if (snd_device < SND_DEVICE_MIN ||
@@ -527,6 +529,11 @@
             audio_extn_dev_arbi_release(snd_device);
             return -EINVAL;
         }
+    } else if (platform_can_split_snd_device(adev->platform, snd_device,
+            &num_devices, new_snd_devices)) {
+        for (i = 0; i < num_devices; i++) {
+            enable_snd_device(adev, new_snd_devices[i]);
+        }
     } else {
         ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
         /* due to the possibility of calibration overwrite between listen
@@ -562,6 +569,8 @@
 int disable_snd_device(struct audio_device *adev,
                        snd_device_t snd_device)
 {
+    int i, num_devices = 0;
+    snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
     char device_name[DEVICE_NAME_MAX_SIZE] = {0};
 
     if (snd_device < SND_DEVICE_MIN ||
@@ -595,6 +604,11 @@
         if (platform_can_enable_spkr_prot_on_device(snd_device) &&
              audio_extn_spkr_prot_is_enabled()) {
             audio_extn_spkr_prot_stop_processing(snd_device);
+        } else if (platform_can_split_snd_device(adev->platform, snd_device,
+                    &num_devices, new_snd_devices)) {
+            for (i = 0; i < num_devices; i++) {
+                disable_snd_device(adev, new_snd_devices[i]);
+            }
         } else {
             audio_route_reset_and_update_path(adev->audio_route, device_name);
         }
@@ -621,15 +635,13 @@
 }
 
 static void check_usecases_codec_backend(struct audio_device *adev,
-                                          struct audio_usecase *uc_info,
-                                          snd_device_t snd_device)
+                                              struct audio_usecase *uc_info,
+                                              snd_device_t snd_device)
 {
     struct listnode *node;
     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
@@ -653,7 +665,6 @@
 
     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.
      */
@@ -663,26 +674,23 @@
     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);
-
-        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,
+        ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
+            "backends match %d",__func__, i,
               platform_get_snd_device_name(snd_device),
-              platform_get_snd_device_name(usecase->out_snd_device));
+              platform_get_snd_device_name(usecase->out_snd_device),
+              platform_check_backends_match(snd_device, 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: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;
-            num_uc_to_switch++;
+            usecase != uc_info &&
+            (usecase->out_snd_device != snd_device || force_routing)  &&
+            usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
+            platform_check_backends_match(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));
+                disable_audio_route(adev, usecase);
+                switch_device[usecase->id] = true;
+                num_uc_to_switch++;
         }
     }