hal: Enable use of ECHO_REFERENCE in AHAL
- Enables echo ref audio source and audio device
- Opens a separate echo reference stream for auto
- Captures echo reference from codec loopback

Change-Id: I95cbd85296ad647149fcf00a297c729ab22ef272
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index d3b2935..c9dac71 100755
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -6096,6 +6096,9 @@
 typedef int (*auto_hal_open_input_stream_t)(struct stream_in*);
 static auto_hal_open_input_stream_t auto_hal_open_input_stream;
 
+typedef int (*auto_hal_open_echo_reference_stream_t)(struct stream_in*);
+static auto_hal_open_echo_reference_stream_t auto_hal_open_echo_reference_stream;
+
 typedef bool (*auto_hal_is_bus_device_usecase_t)(audio_usecase_t);
 static auto_hal_is_bus_device_usecase_t auto_hal_is_bus_device_usecase;
 
@@ -6163,6 +6166,9 @@
             !(auto_hal_open_input_stream =
                  (auto_hal_open_input_stream_t)dlsym(
                             auto_hal_lib_handle, "auto_hal_open_input_stream")) ||
+            !(auto_hal_open_echo_reference_stream =
+                 (auto_hal_open_echo_reference_stream_t)dlsym(
+                            auto_hal_lib_handle, "auto_hal_open_echo_reference_stream")) ||
             !(auto_hal_is_bus_device_usecase =
                  (auto_hal_is_bus_device_usecase_t)dlsym(
                             auto_hal_lib_handle, "auto_hal_is_bus_device_usecase")) ||
@@ -6210,6 +6216,7 @@
     auto_hal_get_car_audio_stream_from_address = NULL;
     auto_hal_open_output_stream = NULL;
     auto_hal_open_input_stream = NULL;
+    auto_hal_open_echo_reference_stream = NULL;
     auto_hal_is_bus_device_usecase = NULL;
     auto_hal_get_audio_port = NULL;
     auto_hal_set_audio_port_config = NULL;
@@ -6293,6 +6300,12 @@
                             auto_hal_open_input_stream(in): -ENOSYS);
 }
 
+int audio_extn_auto_hal_open_echo_reference_stream(struct stream_in *in)
+{
+    return ((auto_hal_open_echo_reference_stream) ?
+                            auto_hal_open_echo_reference_stream(in): 0);
+}
+
 bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id)
 {
     return ((auto_hal_is_bus_device_usecase) ?
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 64b77e8..d4c8fe6 100755
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -1373,6 +1373,7 @@
 int audio_extn_auto_hal_get_car_audio_stream_from_address(const char *address);
 int audio_extn_auto_hal_open_output_stream(struct stream_out *out);
 int audio_extn_auto_hal_open_input_stream(struct stream_in *in);
+int audio_extn_auto_hal_open_echo_reference_stream(struct stream_in *in);
 bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id);
 int audio_extn_auto_hal_get_audio_port(struct audio_hw_device *dev,
                                 struct audio_port *config);
diff --git a/hal/audio_extn/auto_hal.c b/hal/audio_extn/auto_hal.c
index 39f2838..f51bf49 100755
--- a/hal/audio_extn/auto_hal.c
+++ b/hal/audio_extn/auto_hal.c
@@ -336,6 +336,25 @@
     return ret;
 }
 
+/*
+ * Function: auto_hal_open_echo_reference_stream
+ * ---------------------------------------------
+ * opens an input stream to capture an echo reference
+ * and sets for external echo reference
+ *
+ * param *in: stream to be used for echo reference
+ *
+ * returns: 0
+ */
+int auto_hal_open_echo_reference_stream(struct stream_in *in)
+{
+    /* note: this function may be expanded in the future
+    to accommodate other echo reference sources
+    such as an internal AFE loopback. */
+    in->usecase = USECASE_AUDIO_RECORD_ECHO_REF_EXT;
+    return 0;
+}
+
 int auto_hal_open_output_stream(struct stream_out *out)
 {
     int ret = 0;
diff --git a/hal/audio_extn/ext_hw_plugin.c b/hal/audio_extn/ext_hw_plugin.c
index 571ba54..5f21c3f 100644
--- a/hal/audio_extn/ext_hw_plugin.c
+++ b/hal/audio_extn/ext_hw_plugin.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -182,6 +182,7 @@
     case USECASE_AUDIO_RECORD_COMPRESS:
     case USECASE_AUDIO_RECORD_LOW_LATENCY:
     case USECASE_AUDIO_RECORD_FM_VIRTUAL:
+    case USECASE_AUDIO_RECORD_ECHO_REF_EXT:
         *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_CAPTURE;
         break;
     case USECASE_AUDIO_HFP_SCO:
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 83c35c7..5556c34 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -428,6 +428,7 @@
     [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
     [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
     [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
+    [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
 };
 
 static const audio_usecase_t offload_usecases[] = {
@@ -9480,6 +9481,11 @@
         }
     }
 
+    /* reassign use case for echo reference stream on automotive platforms */
+    if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
+        ret = audio_extn_auto_hal_open_echo_reference_stream(in);
+    }
+
     if (in->source == AUDIO_SOURCE_FM_TUNER) {
         if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
             in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 8caefe8..e6794e7 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -250,6 +250,9 @@
 
     USECASE_AUDIO_PLAYBACK_SYNTHESIZER,
 
+    /* Echo reference capture usecases */
+    USECASE_AUDIO_RECORD_ECHO_REF_EXT,
+
     /*Audio FM Tuner usecase*/
     USECASE_AUDIO_FM_TUNER_EXT,
     /*voip usecase with low latency path*/
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 9259150..76cd19a 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -536,6 +536,7 @@
     [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = {FRONT_PASSENGER_PCM_DEVICE, FRONT_PASSENGER_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = {REAR_SEAT_PCM_DEVICE, REAR_SEAT_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = {-1, -1},
+    [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = {MULTIMEDIA2_PCM_DEVICE, MULTIMEDIA2_PCM_DEVICE},
 };
 
 /* Array to store sound devices */
@@ -802,6 +803,7 @@
     [SND_DEVICE_IN_CALL_PROXY] = "call-proxy-in",
     [SND_DEVICE_IN_ICC] = "speaker-mic",
     [SND_DEVICE_IN_SYNTH_MIC] = "speaker-mic",
+    [SND_DEVICE_IN_ECHO_REFERENCE] = "echo-reference",
 };
 
 // Platform specific backend bit width table
@@ -1039,6 +1041,7 @@
     [SND_DEVICE_IN_USB_HEADSET_MULTI_CHANNEL_MIC_AEC] = 162,
     [SND_DEVICE_IN_UNPROCESSED_USB_HEADSET_MULTI_CHANNEL_MIC] = 162,
     [SND_DEVICE_IN_CAPTURE_FM] = 0,
+    [SND_DEVICE_IN_ECHO_REFERENCE] = 100,
     [SND_DEVICE_IN_AANC_HANDSET_MIC] = 104,
     [SND_DEVICE_IN_VOICE_FLUENCE_DMIC_AANC] = 105,
     [SND_DEVICE_IN_QUAD_MIC] = 46,
@@ -1293,6 +1296,7 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_RECOG_USB_HEADSET_MULTI_CHANNEL_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_USB_HEADSET_MULTI_CHANNEL_MIC_AEC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_CAPTURE_FM)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_ECHO_REFERENCE)},
     {TO_NAME_INDEX(SND_DEVICE_IN_AANC_HANDSET_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_FLUENCE_DMIC_AANC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_QUAD_MIC)},
@@ -2679,6 +2683,7 @@
     hw_interface_table[SND_DEVICE_OUT_ICC] = strdup("TERT_TDM_RX_0");
     hw_interface_table[SND_DEVICE_OUT_SYNTH_SPKR] = strdup("TERT_TDM_RX_0");
     hw_interface_table[SND_DEVICE_IN_SYNTH_MIC] = strdup("TERT_TDM_TX_0");
+    hw_interface_table[SND_DEVICE_IN_ECHO_REFERENCE] = strdup("SEC_TDM_TX_0");
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
 
      /*remove ALAC & APE from DSP decoder list based on software decoder availability*/
@@ -7565,6 +7570,8 @@
         }
     } else if (source == AUDIO_SOURCE_FM_TUNER) {
         snd_device = SND_DEVICE_IN_CAPTURE_FM;
+    } else if (source == AUDIO_SOURCE_ECHO_REFERENCE) {
+        snd_device = SND_DEVICE_IN_ECHO_REFERENCE;
     } else if (source == AUDIO_SOURCE_DEFAULT) {
         goto exit;
     }
@@ -7638,6 +7645,8 @@
             snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
         } else if (compare_device_type(&in_devices, AUDIO_DEVICE_IN_FM_TUNER)) {
             snd_device = SND_DEVICE_IN_CAPTURE_FM;
+        } else if (compare_device_type(&in_devices, AUDIO_DEVICE_IN_ECHO_REFERENCE)) {
+            snd_device = SND_DEVICE_IN_ECHO_REFERENCE;
         } else if (audio_extn_usb_connected(NULL) &&
                    is_usb_in_device_type(&in_devices)) {
             snd_device = fixup_usb_headset_mic_snd_device(platform,
@@ -9033,6 +9042,13 @@
 /* Delay in Us */
 int64_t platform_get_audio_source_delay(audio_source_t audio_source)
 {
+    if (audio_source == AUDIO_SOURCE_ECHO_REFERENCE) {
+        /* return 0 because audio source delay is not
+        currently implemented on automotive in the
+        audio_platform_info.xml */
+        return 0;
+    }
+
     if ((audio_source < AUDIO_SOURCE_DEFAULT) ||
             (audio_source > AUDIO_SOURCE_MAX)) {
         ALOGE("%s: Invalid audio_source = %d", __func__, audio_source);
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 5f67510..07cf8be 100755
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -364,6 +364,7 @@
     SND_DEVICE_IN_CALL_PROXY,
     SND_DEVICE_IN_ICC,
     SND_DEVICE_IN_SYNTH_MIC,
+    SND_DEVICE_IN_ECHO_REFERENCE,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,