hal: Add support for external sound devices

Update audio HAL to detect and set the relevant mixer paths for
the sound devices such as speaker, earpiece etc. connected
externally through MI2S backend.

Change-Id: I1e9337a89cb022bce5271b6bde710f633ca2ac29
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index b8fe400..eb092b0 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -184,7 +184,7 @@
         snd_device = usecase->out_snd_device;
 
     strcpy(mixer_path, use_case_table[usecase->id]);
-    platform_add_backend_name(mixer_path, snd_device);
+    platform_add_backend_name(adev->platform, mixer_path, snd_device);
     ALOGV("%s: apply and update mixer path: %s", __func__, mixer_path);
     audio_route_apply_and_update_path(adev->audio_route, mixer_path);
 
@@ -207,7 +207,7 @@
     else
         snd_device = usecase->out_snd_device;
     strcpy(mixer_path, use_case_table[usecase->id]);
-    platform_add_backend_name(mixer_path, snd_device);
+    platform_add_backend_name(adev->platform, mixer_path, snd_device);
     ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
     audio_route_reset_and_update_path(adev->audio_route, mixer_path);
 
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index ae551b9..ef804d2 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -379,7 +379,8 @@
         return "";
 }
 
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(void *platform __unused, char *mixer_path,
+                               snd_device_t snd_device)
 {
     if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
         strcat(mixer_path, " bt-sco");
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index b7acc85..f89439e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -91,6 +91,8 @@
     acdb_send_voice_cal_t acdb_send_voice_cal;
     acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
     struct csd_data *csd;
+    bool ext_speaker;
+    bool ext_earpiece;
 };
 
 static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -485,6 +487,20 @@
     my_data->fluence_in_voice_call = false;
     my_data->fluence_in_voice_rec = false;
 
+    /*
+     * The default assumption is that earpiece (handset), speaker and headphones
+     * devices are connected to internal HW codec and communicated through
+     * slimbus backend. If any platform communicates with speaker or earpiece
+     * or headphones through non-slimbus backend such as MI2S or AUXPCM etc.,
+     * the ext_xxxx flags must be set accordingly.
+     */
+    if (strstr(snd_card_name, "tfa9890_stereo")) {
+        my_data->ext_speaker = true;
+        my_data->ext_earpiece = true;
+    } else if (strstr(snd_card_name, "tfa9890")) {
+        my_data->ext_speaker = true;
+    }
+
     property_get("persist.audio.dualmic.config",value,"");
     if (!strcmp("broadside", value)) {
         my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
@@ -575,8 +591,11 @@
         return "";
 }
 
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(void *platform, char *mixer_path,
+                               snd_device_t snd_device)
 {
+    struct platform_data *my_data = (struct platform_data *)platform;
+
     if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
         strcat(mixer_path, " bt-sco");
     else if(snd_device == SND_DEVICE_OUT_BT_SCO)
@@ -588,6 +607,20 @@
     else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
              snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
         strcat(mixer_path, " bt-sco-wb");
+    else if (my_data->ext_speaker) {
+        if (snd_device == SND_DEVICE_OUT_SPEAKER ||
+            snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+            snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE)
+            strcat(mixer_path, " speaker");
+        else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)
+            strcat(mixer_path, " speaker-and-headphones");
+    } else if (my_data->ext_earpiece &&
+                 (snd_device == SND_DEVICE_OUT_VOICE_HANDSET ||
+                  snd_device == SND_DEVICE_OUT_VOICE_HANDSET_TMUS ||
+                  snd_device == SND_DEVICE_OUT_HANDSET ||
+                  snd_device == SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)) {
+        strcat(mixer_path, " handset");
+    }
 }
 
 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 7079e8c..4a306d5 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -20,7 +20,8 @@
 void *platform_init(struct audio_device *adev);
 void platform_deinit(void *platform);
 const char *platform_get_snd_device_name(snd_device_t snd_device);
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device);
+void platform_add_backend_name(void *platform, char *mixer_path,
+                                                    snd_device_t snd_device);
 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type);
 int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
 int platform_switch_voice_call_device_pre(void *platform);