Merge "configs: Add FFECNS related changes in xml file"
diff --git a/configs/msm8909/msm8909.mk b/configs/msm8909/msm8909.mk
index bc475c6..e8aaf8a 100644
--- a/configs/msm8909/msm8909.mk
+++ b/configs/msm8909/msm8909.mk
@@ -45,6 +45,7 @@
 AUDIO_FEATURE_DISABLED_SOUND_TRIGGER_LEGACY_HAL := true
 AUDIO_FEATURE_ENABLED_COMPRESS_INPUT := true
 AUDIO_FEATURE_ENABLED_CUSTOMSTEREO := true
+COMPILE_HAL_TEST_APPS_IN_VENDOR_IMAGE := true
 
 ##AUDIO_FEATURE_FLAGS
 
@@ -168,7 +169,7 @@
     android.hardware.audio@2.0-service \
     android.hardware.audio@2.0-impl \
     android.hardware.audio.effect@2.0-impl \
-    android.hardware.soundtrigger@2.0-impl \
+    android.hardware.soundtrigger@2.1-impl \
     android.hardware.audio@4.0 \
     android.hardware.audio.common@4.0 \
     android.hardware.audio.common@4.0-util \
diff --git a/configs/msm8996/msm8996.mk b/configs/msm8996/msm8996.mk
index c699535..fb760c1 100644
--- a/configs/msm8996/msm8996.mk
+++ b/configs/msm8996/msm8996.mk
@@ -202,7 +202,7 @@
     android.hardware.audio@2.0-service \
     android.hardware.audio@2.0-impl \
     android.hardware.audio.effect@2.0-impl \
-    android.hardware.soundtrigger@2.0-impl \
+    android.hardware.soundtrigger@2.1-impl \
     android.hardware.audio@4.0 \
     android.hardware.audio.common@4.0 \
     android.hardware.audio.common@4.0-util \
diff --git a/configs/msm8998/msm8998.mk b/configs/msm8998/msm8998.mk
index acd5071..5f4e6e1 100644
--- a/configs/msm8998/msm8998.mk
+++ b/configs/msm8998/msm8998.mk
@@ -232,7 +232,7 @@
     android.hardware.audio@2.0-service \
     android.hardware.audio@2.0-impl \
     android.hardware.audio.effect@2.0-impl \
-    android.hardware.soundtrigger@2.0-impl \
+    android.hardware.soundtrigger@2.1-impl \
     android.hardware.audio@4.0 \
     android.hardware.audio.common@4.0 \
     android.hardware.audio.common@4.0-util \
diff --git a/configs/msmnile/mixer_paths_tavil.xml b/configs/msmnile/mixer_paths_tavil.xml
index b2c8be2..381264c 100644
--- a/configs/msmnile/mixer_paths_tavil.xml
+++ b/configs/msmnile/mixer_paths_tavil.xml
@@ -2709,6 +2709,7 @@
     <path name="voice-tty-full-headset-mic">
         <path name="amic2" />
         <ctl name="ADC2 Volume" value="0" />
+        <ctl name="DEC0 Volume" value="84" />
     </path>
 
     <path name="voice-tty-hco-headset-mic">
diff --git a/configs/msmsteppe/mixer_paths_idp.xml b/configs/msmsteppe/mixer_paths_idp.xml
index e3ce36e..e369875 100644
--- a/configs/msmsteppe/mixer_paths_idp.xml
+++ b/configs/msmsteppe/mixer_paths_idp.xml
@@ -410,6 +410,13 @@
     <ctl name="IIR0 INP2 MUX" value="ZERO" />
     <ctl name="IIR0 INP3 MUX" value="ZERO" />
 
+    <!-- vbat related data -->
+    <ctl name="GSM mode Enable" value="OFF" />
+    <ctl name="WSA_Softclip0 Enable" value="0" />
+    <ctl name="WSA_Softclip1 Enable" value="0" />
+    <ctl name="WSA_RX INT0 VBAT WSA RX0 VBAT Enable" value="0" />
+    <ctl name="WSA_RX INT1 VBAT WSA RX1 VBAT Enable" value="0" />
+
     <!-- Codec controls end -->
 
     <!-- defaults for mmap record -->
@@ -1962,6 +1969,22 @@
         <ctl name="SpkrRight SWR DAC_Port Switch" value="1" />
     </path>
 
+   <path name="speaker-vbat-mono">
+       <path name="speaker-mono" />
+       <ctl name="WSA_RX INT0 VBAT WSA RX0 VBAT Enable" value="1" />
+   </path>
+
+   <path name="speaker-vbat-mono-2">
+       <path name="speaker-mono-2" />
+       <ctl name="WSA_RX INT1 VBAT WSA RX1 VBAT Enable" value="1" />
+   </path>
+
+   <path name="speaker-vbat">
+       <path name="speaker" />
+       <ctl name="WSA_RX INT0 VBAT WSA RX0 VBAT Enable" value="1" />
+       <ctl name="WSA_RX INT1 VBAT WSA RX1 VBAT Enable" value="1" />
+   </path>
+
    <path name="sidetone-iir">
         <ctl name="IIR0 Enable Band1" value="1" />
         <ctl name="IIR0 Enable Band2" value="1" />
@@ -1983,6 +2006,7 @@
         <ctl name="IIR0 INP0 Volume" value="54" />
         <ctl name="IIR0 INP0 MUX" value="DEC0" />
         <ctl name="RX INT2 MIX2 INP" value="SRC0" />
+        <ctl name="WSA_RX0 INT0 SIDETONE MIX" value="SRC0" />
     </path>
 
     <path name="afe-sidetone">
@@ -2023,6 +2047,22 @@
         <path name="speaker-protected" />
     </path>
 
+    <path name="speaker-protected-vbat">
+        <path name="speaker-protected" />
+        <ctl name="WSA_RX INT0 VBAT WSA RX0 VBAT Enable" value="1" />
+        <ctl name="WSA_RX INT1 VBAT WSA RX1 VBAT Enable" value="1" />
+    </path>
+
+    <path name="voice-speaker-protected-vbat">
+        <path name="voice-speaker-protected" />
+        <ctl name="WSA_RX INT0 VBAT WSA RX0 VBAT Enable" value="1" />
+    </path>
+
+    <path name="voice-speaker-2-protected-vbat">
+        <path name="voice-speaker-2-protected" />
+        <ctl name="WSA_RX INT1 VBAT WSA RX1 VBAT Enable" value="1" />
+    </path>
+
     <path name="vi-feedback">
     </path>
 
@@ -2102,6 +2142,14 @@
         <path name="speaker-mono-2" />
     </path>
 
+    <path name="voice-speaker-vbat">
+        <path name="speaker-vbat-mono" />
+    </path>
+
+    <path name="voice-speaker-2-vbat">
+        <path name="speaker-vbat-mono-2" />
+    </path>
+
     <path name="voice-speaker-mic">
         <path name="speaker-mic" />
     </path>
diff --git a/configs/msmsteppe/mixer_paths_qrd.xml b/configs/msmsteppe/mixer_paths_qrd.xml
index f0227c9..e029708 100644
--- a/configs/msmsteppe/mixer_paths_qrd.xml
+++ b/configs/msmsteppe/mixer_paths_qrd.xml
@@ -2038,7 +2038,7 @@
 
     <path name="sidetone-headphones">
         <path name="sidetone-iir" />
-        <ctl name="IIR0 INP0 Volume" value="54" />
+        <ctl name="IIR0 INP0 Volume" value="40" />
         <ctl name="IIR0 INP0 MUX" value="DEC0" />
         <ctl name="RX INT0 MIX2 INP" value="SRC0" />
         <ctl name="RX INT1 MIX2 INP" value="SRC0" />
@@ -2048,7 +2048,7 @@
         <path name="sidetone-iir" />
         <ctl name="IIR0 INP0 Volume" value="54" />
         <ctl name="IIR0 INP0 MUX" value="DEC0" />
-        <ctl name="RX INT2 MIX2 INP" value="SRC0" />
+        <ctl name="RX INT0 MIX2 INP" value="SRC0" />
     </path>
 
     <path name="afe-sidetone">
diff --git a/configs/sdm660/sdm660.mk b/configs/sdm660/sdm660.mk
index b0bd431..aef78b1 100644
--- a/configs/sdm660/sdm660.mk
+++ b/configs/sdm660/sdm660.mk
@@ -244,7 +244,7 @@
     android.hardware.audio@2.0-service \
     android.hardware.audio@2.0-impl \
     android.hardware.audio.effect@2.0-impl \
-    android.hardware.soundtrigger@2.0-impl \
+    android.hardware.soundtrigger@2.1-impl \
     android.hardware.audio@4.0 \
     android.hardware.audio.common@4.0 \
     android.hardware.audio.common@4.0-util \
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index e80e286..1a72bf8 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -1877,10 +1877,12 @@
 
      ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
      if (ret >= 0) {
-         if (a2dp.bt_lib_handle && (a2dp.bt_state != A2DP_STATE_DISCONNECTED) ) {
+         if (a2dp.bt_lib_handle) {
              if ((!strncmp(value,"true",sizeof(value)))) {
                 ALOGD("Setting a2dp to suspend state");
                 a2dp.a2dp_suspended = true;
+                if (a2dp.bt_state == A2DP_STATE_DISCONNECTED)
+                    goto param_handled;
                 list_for_each(node, &a2dp.adev->usecase_list) {
                     uc_info = node_to_item(node, struct audio_usecase, list);
                     if (uc_info->type == PCM_PLAYBACK &&
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 5b388a8..d125b2f 100755
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -72,6 +72,7 @@
     uint32_t proxy_channel_num;
     bool hpx_enabled;
     bool vbat_enabled;
+    bool bcl_enabled;
     bool hifi_audio_enabled;
     bool ras_enabled;
     struct aptx_dec_bt_addr addr;
@@ -414,6 +415,25 @@
     ALOGD("%s: vbat.enabled property is set to %s", __func__, prop_vbat_enabled);
     return (aextnmod.vbat_enabled ? true: false);
 }
+
+bool audio_extn_is_bcl_enabled(void)
+{
+    ALOGD("%s: status: %d", __func__, aextnmod.bcl_enabled);
+    return (aextnmod.bcl_enabled ? true: false);
+}
+
+bool audio_extn_can_use_bcl(void)
+{
+    char prop_bcl_enabled[PROPERTY_VALUE_MAX] = "false";
+
+    property_get("persist.vendor.audio.bcl.enabled", prop_bcl_enabled, "0");
+    if (!strncmp("true", prop_bcl_enabled, 4)) {
+        aextnmod.bcl_enabled = 1;
+    }
+
+    ALOGD("%s: bcl.enabled property is set to %s", __func__, prop_bcl_enabled);
+    return (aextnmod.bcl_enabled ? true: false);
+}
 #endif
 
 #ifdef RAS_ENABLED
@@ -824,6 +844,7 @@
     aextnmod.proxy_channel_num = 2;
     aextnmod.hpx_enabled = 0;
     aextnmod.vbat_enabled = 0;
+    aextnmod.bcl_enabled = 0;
     aextnmod.hifi_audio_enabled = 0;
     aextnmod.addr.nap = 0;
     aextnmod.addr.uap = 0;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 365b03e..d3e7a5f 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -169,9 +169,13 @@
 #ifndef VBAT_MONITOR_ENABLED
 #define audio_extn_is_vbat_enabled()                     (0)
 #define audio_extn_can_use_vbat()                        (0)
+#define audio_extn_is_bcl_enabled()                     (0)
+#define audio_extn_can_use_bcl()                        (0)
 #else
 bool audio_extn_is_vbat_enabled(void);
 bool audio_extn_can_use_vbat(void);
+bool audio_extn_is_bcl_enabled(void);
+bool audio_extn_can_use_bcl(void);
 #endif
 
 #ifndef RAS_ENABLED
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 0ea8b56..0a48953 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -873,6 +873,25 @@
     }
 }
 
+void audio_extn_btsco_get_sample_rate(int snd_device, int *sample_rate)
+{
+    switch (snd_device) {
+    case SND_DEVICE_OUT_BT_SCO:
+    case SND_DEVICE_IN_BT_SCO_MIC:
+    case SND_DEVICE_IN_BT_SCO_MIC_NREC:
+        *sample_rate = 8000;
+        break;
+    case SND_DEVICE_OUT_BT_SCO_WB:
+    case SND_DEVICE_IN_BT_SCO_MIC_WB:
+    case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
+        *sample_rate = 16000;
+        break;
+    default:
+        ALOGD("%s:Not a BT SCO device, need not update sampling rate\n", __func__);
+        break;
+    }
+}
+
 static int send_app_type_cfg_for_device(struct audio_device *adev,
                                         struct audio_usecase *usecase,
                                         int split_snd_device)
@@ -939,8 +958,13 @@
         goto exit_send_app_type_cfg;
     }
     snd_device = platform_get_spkr_prot_snd_device(snd_device);
-
-    acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+    if (voice_is_in_call_rec_stream(usecase->stream.in) && usecase->type == PCM_CAPTURE) {
+        snd_device_t voice_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
+        acdb_dev_id = platform_get_snd_device_acdb_id(voice_device);
+        ALOGV("acdb id for voice call use case %d", acdb_dev_id);
+    } else {
+        acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+    }
     if (acdb_dev_id <= 0) {
         ALOGE("%s: Couldn't get the acdb dev id", __func__);
         rc = -EINVAL;
@@ -996,6 +1020,7 @@
                    ALOGI("%s using %d sample rate rate for A2DP CoPP",
                         __func__, usecase->stream.out->app_type_cfg.sample_rate);
         }
+        audio_extn_btsco_get_sample_rate(snd_device, &usecase->stream.out->app_type_cfg.sample_rate);
         sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
 
         /* Interactive streams are supported with only direct app type id.
@@ -1038,6 +1063,11 @@
         app_type_cfg[len++] = acdb_dev_id;
         if (usecase->id == USECASE_AUDIO_RECORD_VOIP)
             usecase->stream.in->app_type_cfg.sample_rate = usecase->stream.in->sample_rate;
+        if (voice_is_in_call_rec_stream(usecase->stream.in)) {
+            audio_extn_btsco_get_sample_rate(usecase->in_snd_device, &usecase->stream.in->app_type_cfg.sample_rate);
+        } else {
+            audio_extn_btsco_get_sample_rate(snd_device, &usecase->stream.in->app_type_cfg.sample_rate);
+        }
         sample_rate = usecase->stream.in->app_type_cfg.sample_rate;
         app_type_cfg[len++] = sample_rate;
         if (snd_device_be_idx > 0)
@@ -1071,6 +1101,7 @@
 {
     int i, num_devices = 0;
     snd_device_t new_snd_devices[SND_DEVICE_OUT_END] = {0};
+    snd_device_t in_snd_device = usecase->in_snd_device;
     int rc = 0;
 
     switch (usecase->type) {
@@ -1089,11 +1120,14 @@
     case PCM_CAPTURE:
         ALOGD("%s: usecase->in_snd_device %s",
               __func__, platform_get_snd_device_name(usecase->in_snd_device));
+        if (voice_is_in_call_rec_stream(usecase->stream.in)) {
+            in_snd_device = voice_get_incall_rec_backend_device(usecase->stream.in);
+        }
         /* check for in combo device */
         if (platform_split_snd_device(adev->platform,
-                                      usecase->in_snd_device,
+                                      in_snd_device,
                                       &num_devices, new_snd_devices)) {
-            new_snd_devices[0] = usecase->in_snd_device;
+            new_snd_devices[0] = in_snd_device;
             num_devices = 1;
         }
         break;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 225a03e..904b369 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1303,8 +1303,8 @@
         if (platform_check_backends_match(d3[0], d3[1])) {
             return d2; // case 5
         } else {
-            // check if d1 and d3[1] are related
-            if (d1 == d3[1])
+            // check if d1 is related to any of d3's
+            if (d1 == d3[0] || d1 == d3[1])
                 return d1; // case 1
             else
                 return d3[1]; // case 8
@@ -3563,6 +3563,7 @@
 static int out_on_error(struct audio_stream *stream)
 {
     struct stream_out *out = (struct stream_out *)stream;
+    int status = 0;
 
     lock_output_stream(out);
     // always send CMD_ERROR for offload streams, this
@@ -3570,11 +3571,18 @@
     // since the stream is active, offload_callback_thread is also active.
     if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
         stop_compressed_output_l(out);
+    }
+    pthread_mutex_unlock(&out->lock);
+
+    status = out_standby(&out->stream.common);
+
+    lock_output_stream(out);
+    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
         send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
     }
     pthread_mutex_unlock(&out->lock);
 
-    return out_standby(&out->stream.common);
+    return status;
 }
 
 /*
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index c6d1a74..5f80a8d 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -567,6 +567,9 @@
     [SND_DEVICE_IN_EC_REF_LOOPBACK_MONO] = "ec-ref-loopback-mono",
     [SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO] = "ec-ref-loopback-stereo",
     [SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = "quad-mic",
+    [SND_DEVICE_IN_INCALL_REC_RX] = "incall-rec-rx",
+    [SND_DEVICE_IN_INCALL_REC_TX] = "incall-rec-tx",
+    [SND_DEVICE_IN_INCALL_REC_RX_TX] = "incall-rec-rx-tx",
 };
 
 // Platform specific backend bit width table
@@ -899,6 +902,9 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_EC_REF_LOOPBACK_MONO)},
     {TO_NAME_INDEX(SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_GENERIC_QMIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_TX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX_TX)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -1741,6 +1747,8 @@
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_RX] = strdup("INCALL_RECORD_RX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_TX] = strdup("INCALL_RECORD_TX");
 
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
     /*remove ALAC & APE from DSP decoder list based on software decoder availability*/
@@ -3899,6 +3907,11 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_BT_A2DP;
         ret = 0;
+    } else if (SND_DEVICE_IN_INCALL_REC_RX_TX == snd_device) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_IN_INCALL_REC_RX;
+        new_snd_devices[1] = SND_DEVICE_IN_INCALL_REC_TX;
+        ret = 0;
     }
 
     ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 3779c29..6236746 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -241,6 +241,9 @@
     SND_DEVICE_IN_EC_REF_LOOPBACK_MONO,
     SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO,
     SND_DEVICE_IN_HANDSET_GENERIC_QMIC,
+    SND_DEVICE_IN_INCALL_REC_RX,
+    SND_DEVICE_IN_INCALL_REC_TX,
+    SND_DEVICE_IN_INCALL_REC_RX_TX,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 0b7fee6..509dbc5 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -238,6 +238,7 @@
     bool is_acdb_initialized;
     /* Vbat monitor related flags */
     bool is_vbat_speaker;
+    bool is_bcl_speaker;
     bool gsm_mode_enabled;
     bool is_slimbus_interface;
     bool is_internal_codec;
@@ -553,6 +554,9 @@
     [SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = "unprocessed-quad-mic",
     [SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = "unprocessed-headset-mic",
     [SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = "quad-mic",
+    [SND_DEVICE_IN_INCALL_REC_RX] = "incall-rec-rx",
+    [SND_DEVICE_IN_INCALL_REC_TX] = "incall-rec-tx",
+    [SND_DEVICE_IN_INCALL_REC_RX_TX] = "incall-rec-rx-tx",
 };
 
 // Platform specific backend bit width table
@@ -889,6 +893,9 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_QUAD_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_GENERIC_QMIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_TX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_INCALL_REC_RX_TX)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -1626,6 +1633,8 @@
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_HANDSET_GENERIC_QMIC] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_RX] = strdup("INCALL_RECORD_RX");
+    hw_interface_table[SND_DEVICE_IN_INCALL_REC_TX] = strdup("INCALL_RECORD_TX");
 
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
 
@@ -1751,6 +1760,9 @@
         ret = 0;
 
         if ((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+           /* VBAT BCL speaker does not need tuning data */
+           if (!plat_data->is_bcl_speaker)
+               return;
            ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
            if (ret < 0)
                ALOGE("%s error in sending vbat adc data to acdb", __func__);
@@ -2218,6 +2230,10 @@
     if (ret)
         my_data->is_vbat_speaker = true;
 
+    ret = audio_extn_can_use_bcl();
+    if (ret)
+        my_data->is_bcl_speaker = true;
+
     list_init(&my_data->acdb_meta_key_list);
 
     set_platform_defaults(my_data);
@@ -3408,7 +3424,7 @@
          out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
          out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_2_VBAT) &&
          audio_extn_spkr_prot_is_enabled()) {
-        if (my_data->is_vbat_speaker)
+        if (my_data->is_vbat_speaker || my_data->is_bcl_speaker)
             acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
         else
             acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
@@ -3483,7 +3499,7 @@
          out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
          out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_2_VBAT) &&
          audio_extn_spkr_prot_is_enabled()) {
-        if (my_data->is_vbat_speaker)
+        if (my_data->is_vbat_speaker || my_data->is_bcl_speaker)
             acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
          else
             acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
@@ -3781,6 +3797,11 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
         new_snd_devices[1] = SND_DEVICE_OUT_BT_A2DP;
         ret = 0;
+    } else if (SND_DEVICE_IN_INCALL_REC_RX_TX == snd_device) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_IN_INCALL_REC_RX;
+        new_snd_devices[1] = SND_DEVICE_IN_INCALL_REC_TX;
+        ret = 0;
     }
 
     ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
@@ -4005,7 +4026,7 @@
             else
                 snd_device = SND_DEVICE_OUT_BT_SCO;
         } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
-                if (my_data->is_vbat_speaker) {
+                if (my_data->is_vbat_speaker || my_data->is_bcl_speaker) {
                     if (hw_info_is_stereo_spkr(my_data->hw_info)) {
                         if (my_data->mono_speaker == SPKR_1)
                             snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_VBAT;
@@ -4089,7 +4110,7 @@
             snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_2;
         else if (adev->speaker_lr_swap)
             snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
-        else if (my_data->is_vbat_speaker)
+        else if (my_data->is_vbat_speaker || my_data->is_bcl_speaker)
             snd_device = SND_DEVICE_OUT_SPEAKER_VBAT;
         else
             snd_device = SND_DEVICE_OUT_SPEAKER;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 6fdb499..28a3248 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -247,6 +247,9 @@
     SND_DEVICE_IN_EC_REF_LOOPBACK_MONO,
     SND_DEVICE_IN_EC_REF_LOOPBACK_STEREO,
     SND_DEVICE_IN_HANDSET_GENERIC_QMIC,
+    SND_DEVICE_IN_INCALL_REC_RX,
+    SND_DEVICE_IN_INCALL_REC_TX,
+    SND_DEVICE_IN_INCALL_REC_RX_TX,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
diff --git a/hal/voice.c b/hal/voice.c
index 425bb54..7b93cfd 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -440,6 +440,27 @@
     return ret;
 }
 
+snd_device_t voice_get_incall_rec_backend_device(struct stream_in *in)
+{
+   snd_device_t incall_record_device = {0};
+
+   switch(in->source) {
+    case AUDIO_SOURCE_VOICE_UPLINK:
+        incall_record_device = SND_DEVICE_IN_INCALL_REC_TX;
+        break;
+    case AUDIO_SOURCE_VOICE_DOWNLINK:
+         incall_record_device = SND_DEVICE_IN_INCALL_REC_RX;
+         break;
+    case AUDIO_SOURCE_VOICE_CALL:
+         incall_record_device = SND_DEVICE_IN_INCALL_REC_RX_TX;
+         break;
+    default:
+        ALOGI("Invalid source %d", in->source);
+    }
+
+   return incall_record_device;
+}
+
 snd_device_t voice_get_incall_rec_snd_device(snd_device_t in_snd_device)
 {
     snd_device_t incall_record_device = in_snd_device;
diff --git a/hal/voice.h b/hal/voice.h
index 2ef790a..bc9aa21 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -103,5 +103,5 @@
                                       bool enable);
 bool voice_is_call_state_active(struct audio_device *adev);
 void voice_set_device_mute_flag (struct audio_device *adev, bool state);
-
+snd_device_t voice_get_incall_rec_backend_device(struct stream_in *in);
 #endif //VOICE_H