hal: Add codec EC reference support

- We need to set codec EC reference instead of MSM/AFE
  EC ref for Native audio usecase along with other
  usecases running on 48K port. In this scenario we
  will run two AFE ports, one regular port and the
  other port running at 44.1KHz and mixing done in codec.
  So set appropriate codec EC reference.

- One example of such usecase is VoIP over audio path
  and a 44.1KHz stream playback. But this change is generic
  enough to accommodate other possible usecases if any.

Change-Id: Ib980e36d111c1671303abe2b19341568d9fd2331
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 4df1c01..713467b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -224,6 +224,7 @@
     struct csd_data *csd;
     void *edid_info;
     bool edid_valid;
+    char ec_ref_mixer_path[64];
     codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
 };
 
@@ -770,23 +771,34 @@
     return ret_val;
 }
 
-void platform_set_echo_reference(void *platform, bool enable)
+void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device)
 {
-    struct platform_data *my_data = (struct platform_data *)platform;
-    struct audio_device *adev = my_data->adev;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+    struct stream_out out;
 
-    if (my_data->ec_ref_enabled) {
-        my_data->ec_ref_enabled = false;
-        ALOGV("%s: disabling echo-reference", __func__);
-        audio_route_reset_and_update_path(adev->audio_route, "echo-reference");
+    out.devices = out_device;
+
+    if (strcmp(my_data->ec_ref_mixer_path, "")) {
+        ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
+        audio_route_reset_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
     }
 
     if (enable) {
-         my_data->ec_ref_enabled = true;
-         ALOGD("%s: enabling echo-reference", __func__);
-         audio_route_apply_and_update_path(adev->audio_route, "echo-reference");
-    }
+        strlcpy(my_data->ec_ref_mixer_path, "echo-reference", sizeof(my_data->ec_ref_mixer_path));
+        snd_device = platform_get_output_snd_device(adev->platform, &out);
+        /*
+         * If native audio device reference count > 0, then apply codec EC otherwise
+         * fallback to headphones if so or default
+         */
+        if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
+            platform_add_backend_name(my_data->ec_ref_mixer_path, SND_DEVICE_OUT_HEADPHONES_44_1);
+        else
+            platform_add_backend_name(my_data->ec_ref_mixer_path, snd_device);
 
+        ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
+        audio_route_apply_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
+    }
 }
 
 static struct csd_data *open_csd_client(bool i2s_ext_modem)
@@ -2363,14 +2375,14 @@
                 my_data->fluence_in_voice_call == false) {
                 snd_device = SND_DEVICE_IN_HANDSET_MIC;
                 if (audio_extn_hfp_is_active(adev))
-                    platform_set_echo_reference(adev->platform, true);
+                    platform_set_echo_reference(adev, true, out_device);
             } else {
                 snd_device = SND_DEVICE_IN_VOICE_DMIC;
             }
         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
             snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
             if (audio_extn_hfp_is_active(adev))
-                platform_set_echo_reference(adev->platform, true);
+                platform_set_echo_reference(adev, true, out_device);
         } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
             if (adev->bt_wb_speech_enabled) {
                 if (adev->bluetooth_nrec)
@@ -2398,7 +2410,7 @@
             } else {
                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
                 if (audio_extn_hfp_is_active(adev))
-                    platform_set_echo_reference(adev->platform, true);
+                    platform_set_echo_reference(adev, true, out_device);
             }
         } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX)
             snd_device = SND_DEVICE_IN_VOICE_RX;
@@ -2446,7 +2458,7 @@
                 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                     snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                 }
-                platform_set_echo_reference(adev->platform, true);
+                platform_set_echo_reference(adev, true, out_device);
             } else if (adev->active_input->enable_aec) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode) {
@@ -2468,7 +2480,7 @@
                 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                     snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                 }
-                platform_set_echo_reference(adev->platform, true);
+                platform_set_echo_reference(adev, true, out_device);
             } else if (adev->active_input->enable_ns) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode) {
@@ -2490,9 +2502,9 @@
                 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                     snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                 }
-                platform_set_echo_reference(adev->platform, false);
+                platform_set_echo_reference(adev, false, out_device);
             } else
-                platform_set_echo_reference(adev->platform, false);
+                platform_set_echo_reference(adev, false, out_device);
         }
     } else if (source == AUDIO_SOURCE_MIC) {
         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
@@ -2500,10 +2512,10 @@
             if(my_data->fluence_in_audio_rec) {
                 if(my_data->fluence_type & FLUENCE_QUAD_MIC) {
                     snd_device = SND_DEVICE_IN_HANDSET_QMIC;
-                    platform_set_echo_reference(adev->platform, true);
+                    platform_set_echo_reference(adev, true, out_device);
                 } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
                     snd_device = SND_DEVICE_IN_HANDSET_DMIC;
-                    platform_set_echo_reference(adev->platform, true);
+                    platform_set_echo_reference(adev, true, out_device);
                 }
             }
         }
@@ -3455,9 +3467,11 @@
     ALOGI("%s 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
+    // 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) {
+    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__);
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;