Merge "audio: platform: Support Ambisonic capture usecase in multi-record"
diff --git a/configs/sdm845/mixer_paths_i2s.xml b/configs/sdm845/mixer_paths_i2s.xml
index 75d984f..86dd74e 100644
--- a/configs/sdm845/mixer_paths_i2s.xml
+++ b/configs/sdm845/mixer_paths_i2s.xml
@@ -144,9 +144,9 @@
     </path>
 
     <path name="adc2">
-        <ctl name="AIF1_CAP Mixer SLIM TX6" value="1"/>
-        <ctl name="MI2S_TX Channels" value="One" />
-        <ctl name="SLIM TX6 MUX" value="DEC6" />
+        <ctl name="AIF1_CAP Mixer I2S TX6" value="1"/>
+        <ctl name="CDC_IF TX6 MUX" value="DEC6" />
+        <ctl name="PRI_MI2S_TX Channels" value="One" />
         <ctl name="ADC MUX6" value="AMIC" />
         <ctl name="AMIC MUX6" value="ADC2" />
     </path>
@@ -208,6 +208,7 @@
 
     <path name="handset-mic">
         <path name="adc2" />
+        <ctl name="DEC6 Volume" value="84" />
     </path>
 
     <path name="headphones">
@@ -226,11 +227,11 @@
 
     <path name="headset-mic">
         <path name="adc2" />
-        <ctl name="DEC8 Volume" value="84" />
+        <ctl name="DEC6 Volume" value="84" />
     </path>
 
     <path name="voice-handset">
-        <path name="handset" />
+        <path name="headphones" />
     </path>
 
     <path name="voice-handset-tmus">
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 589a391..4647d7a 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 - 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2018, 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
@@ -69,11 +69,11 @@
 /* Min and max resistance value in lookup table. */
 #define MIN_RESISTANCE_LOOKUP (3.2)
 #define MAX_RESISTANCE_LOOKUP (8)
-#define SPV3_LOOKUP_TABLE_ROWS (49)
+#define SPKR_PROT_LOOKUP_TABLE_ROWS (49)
 /* default limiter threshold is 0dB(0x7FFFFFF in natural value) */
 #define DEFAULT_LIMITER_TH (0x07FFFFFF)
 #define AFE_API_VERSION_SUPPORT_SPV3 (0x2)
-enum spv3_boost_max_state {
+enum wcd_boost_max_state {
     BOOST_NO_MAX_STATE,
     BOOST_MAX_STATE_1,
     BOOST_MAX_STATE_2,
@@ -205,65 +205,65 @@
     char *spkr_2_name;
 };
 
-struct spv3_boost {
+struct spkr_prot_boost {
     /* bit7-4: first stage; bit 3-0: second stage */
     int boost_value;
     int max_state;
 };
 
-#define SPV3_BOOST_VALUE_STATE(value, state) \
+#define SPKR_PROT_BOOST_VALUE_STATE(value, state) \
 {    .boost_value = (value), .max_state = (state) }
 
-static struct spv3_boost spv3_boost_lookup_table[SPV3_LOOKUP_TABLE_ROWS] = {
-    SPV3_BOOST_VALUE_STATE(0xc7, BOOST_MAX_STATE_1),
-    SPV3_BOOST_VALUE_STATE(0xd7, BOOST_MAX_STATE_1),
-    SPV3_BOOST_VALUE_STATE(0xd7, BOOST_MAX_STATE_1),
-    SPV3_BOOST_VALUE_STATE(0xe7, BOOST_MAX_STATE_1),
-    SPV3_BOOST_VALUE_STATE(0xe7, BOOST_MAX_STATE_1),
-    SPV3_BOOST_VALUE_STATE(0xf7, BOOST_MAX_STATE_1),
-    SPV3_BOOST_VALUE_STATE(0x70, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x70, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x71, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x71, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x72, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x72, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x73, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x73, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x74, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x75, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x75, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x76, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x76, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x77, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x77, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x78, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x78, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x79, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x79, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7a, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7a, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7a, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7b, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7b, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7c, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7c, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7d, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7d, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7e, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7e, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
-    SPV3_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+static struct spkr_prot_boost spkr_prot_boost_lookup_table[SPKR_PROT_LOOKUP_TABLE_ROWS] = {
+    SPKR_PROT_BOOST_VALUE_STATE(0xc7, BOOST_MAX_STATE_1),
+    SPKR_PROT_BOOST_VALUE_STATE(0xd7, BOOST_MAX_STATE_1),
+    SPKR_PROT_BOOST_VALUE_STATE(0xd7, BOOST_MAX_STATE_1),
+    SPKR_PROT_BOOST_VALUE_STATE(0xe7, BOOST_MAX_STATE_1),
+    SPKR_PROT_BOOST_VALUE_STATE(0xe7, BOOST_MAX_STATE_1),
+    SPKR_PROT_BOOST_VALUE_STATE(0xf7, BOOST_MAX_STATE_1),
+    SPKR_PROT_BOOST_VALUE_STATE(0x70, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x70, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x71, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x71, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x72, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x72, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x73, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x73, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x74, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x75, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x75, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x76, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x76, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x77, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x77, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x78, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x78, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x79, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x79, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7a, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7a, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7a, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7b, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7b, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7c, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7c, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7d, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7d, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7e, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7e, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
+    SPKR_PROT_BOOST_VALUE_STATE(0x7f, BOOST_MAX_STATE_2),
 };
 
 /* 3.2 ohm in q24 format: (3.2 * (1 << 24)) */
@@ -274,7 +274,7 @@
 #define LOOKUP_RESISTANCE_GAP_SPKR_Q24    (1677722)
 
 /* 3.2ohm : 0.1ohm : 8ohm lookup table */
-static int spv3_limiter_th_q27_table[SPV3_LOOKUP_TABLE_ROWS] = {
+static int spv3_limiter_th_q27_table[SPKR_PROT_LOOKUP_TABLE_ROWS] = {
     85469248, 86758070, 88066327, 89394311, 90637910, 91898809,
     93070036, 94364769, 95567425, 96674043, 97906130, 99039829,
     100186656, 101346763, 102402340, 103588104, 104667026, 105757185,
@@ -566,14 +566,14 @@
    return handle.wsa_found;
 }
 
-static void audio_extn_check_wsa_support_sp_v3(struct audio_device *adev,
-                unsigned int num_of_spkrs, bool *wsa_support_spv3)
+static void audio_extn_check_wsa(struct audio_device *adev,
+                unsigned int num_of_spkrs, bool *wsa_is_8815)
 {
     unsigned int i = 0;
     if (!is_wsa_present() ||
         platform_spkr_prot_is_wsa_analog_mode(adev)){
         for (i = 0; i < num_of_spkrs; i++)
-            wsa_support_spv3[i] = false;
+            wsa_is_8815[i] = false;
 
         return;
     }
@@ -582,9 +582,9 @@
             sizeof(WSA8815_NAME_LEFT)) ||
             !strncmp(WSA8815_NAME_RIGHT, tz_names.spkr_1_name,
                 sizeof(WSA8815_NAME_RIGHT))) {
-        wsa_support_spv3[SP_V2_SPKR_1] = true;
+        wsa_is_8815[SP_V2_SPKR_1] = true;
     } else {
-        wsa_support_spv3[SP_V2_SPKR_1] = false;
+        wsa_is_8815[SP_V2_SPKR_1] = false;
         ALOGI("%s: Speaker1(%s) is not wsa8815.", __func__, tz_names.spkr_1_name);
     }
 
@@ -593,9 +593,9 @@
                     sizeof(WSA8815_NAME_RIGHT)) ||
             !strncmp(WSA8815_NAME_LEFT, tz_names.spkr_2_name,
                     sizeof(WSA8815_NAME_LEFT)))) {
-        wsa_support_spv3[SP_V2_SPKR_2] = true;
+        wsa_is_8815[SP_V2_SPKR_2] = true;
     } else {
-        wsa_support_spv3[SP_V2_SPKR_2] = false;
+        wsa_is_8815[SP_V2_SPKR_2] = false;
         ALOGI("%s: Speaker2(%s) is not wsa8815.", __func__, tz_names.spkr_2_name);
     }
 
@@ -646,7 +646,7 @@
     }
 
     status = mixer_ctl_set_value(ctl, 0,
-                    spv3_boost_lookup_table[boost_table_index].boost_value);
+                    spkr_prot_boost_lookup_table[boost_table_index].boost_value);
 
     if (status < 0) {
         ALOGE("%s: Could not set ctl for mixer %s\n", __func__,
@@ -657,7 +657,8 @@
     return 0;
 }
 
-static int audio_extn_config_spv3(struct audio_device *adev, unsigned int wsa_num)
+static int audio_extn_spkr_boost_update(struct audio_device *adev,
+                unsigned int wsa_num, unsigned int *index )
 {
     float dcr = 0;
     unsigned int r0_index = 0;
@@ -679,12 +680,12 @@
     }
 
     r0_index = (int)((dcr - MIN_RESISTANCE_LOOKUP) * 10);
-    if (r0_index >= SPV3_LOOKUP_TABLE_ROWS) {
+    if (r0_index >= SPKR_PROT_LOOKUP_TABLE_ROWS) {
         ALOGE("%s: r0_index=%d overflows.", __func__, r0_index);
         return -EINVAL;
     }
 
-    boost_max_state = spv3_boost_lookup_table[r0_index].max_state;
+    boost_max_state = spkr_prot_boost_lookup_table[r0_index].max_state;
     ret = audio_extn_set_wcd_boost_max_state(adev, boost_max_state, wsa_num);
     if (ret < 0) {
         ALOGE("%s: failed to set wcd max boost state.",
@@ -699,32 +700,47 @@
         return -EINVAL;
     }
 
-    handle.limiter_th[wsa_num] = spv3_limiter_th_q27_table[r0_index];
+    *index = r0_index;
 
     return 0;
 }
 
-static void audio_extn_check_config_sp_v3(struct audio_device *adev,
+static void audio_extn_set_boost_and_limiter(struct audio_device *adev,
                 bool spv3_enable, unsigned int afe_api_version)
 {
     int chn = 0;
-    bool wsa_support_spv3[SP_V2_NUM_MAX_SPKRS] = {false, false};
+    bool wsa_is_8815[SP_V2_NUM_MAX_SPKRS] = {false, false};
+    unsigned int r0_index = 0;
 
-    if (spv3_enable && afe_api_version >= AFE_API_VERSION_SUPPORT_SPV3) {
-        handle.sp_version = SP_V2;
-        audio_extn_check_wsa_support_sp_v3(adev, vi_feed_no_channels, wsa_support_spv3);
-        /*
-         * In case of WSA8815+8810, invalid limiter threshold is sent to DSP
-         * for WSA8810 speaker. DSP ignores the invalid value and use default one.
-         * The approach let spv3 apply on 8815 and spv2 on 8810 respectively.
-         */
-        for (chn = 0; chn < vi_feed_no_channels; chn++) {
-            if (wsa_support_spv3[chn] && !audio_extn_config_spv3(adev, chn))
-                handle.sp_version = SP_V3;
-            else
-                handle.limiter_th[chn] = DEFAULT_LIMITER_TH;
+    handle.sp_version = SP_V2;
+
+    /*
+     * As long as speaker protection is enabled, WCD and WSA
+     * follow lookup table based on R0 impediance regardless
+     * of spv2 or spv3.
+     */
+    audio_extn_check_wsa(adev, vi_feed_no_channels, wsa_is_8815);
+    /*
+     * In case of WSA8815+8810, invalid limiter threshold is sent to DSP
+     * for WSA8810 speaker. DSP ignores the invalid value and use default one.
+     * The approach let spv3 apply on 8815 and spv2 on 8810 respectively.
+     */
+    for (chn = 0; chn < vi_feed_no_channels; chn++) {
+        if (wsa_is_8815[chn] && !audio_extn_spkr_boost_update(adev, chn, &r0_index)) {
+            handle.limiter_th[chn] = spv3_limiter_th_q27_table[r0_index];
+            handle.sp_version = SP_V3;
+        }
+        else {
+            handle.limiter_th[chn] = DEFAULT_LIMITER_TH;
         }
     }
+
+    /*
+     * If spv3 is disabld or ADSP version doesn't comply,
+     * ADSP works with SP_V2 version.
+     */
+    if (!spv3_enable || afe_api_version < AFE_API_VERSION_SUPPORT_SPV3)
+        handle.sp_version = SP_V2;
 }
 
 static int spkr_calibrate(int t0_spk_1, int t0_spk_2)
@@ -1059,7 +1075,7 @@
                 handle.spkr_prot_mode = MSM_SPKR_PROT_CALIBRATED;
             close(acdb_fd);
 
-            audio_extn_check_config_sp_v3(adev, spv3_enable, vi_feed_no_channels);
+            audio_extn_set_boost_and_limiter(adev, spv3_enable, vi_feed_no_channels);
 
             pthread_exit(0);
             return NULL;
@@ -1213,7 +1229,7 @@
         dlclose(handle.thermal_handle);
     handle.thermal_handle = NULL;
 
-    audio_extn_check_config_sp_v3(adev, spv3_enable, vi_feed_no_channels);
+    audio_extn_set_boost_and_limiter(adev, spv3_enable, vi_feed_no_channels);
 
     pthread_exit(0);
     return NULL;
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index 4b70fb7..26c92ec 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -425,6 +425,20 @@
     ALOGW("%s: Not a msmnile device", __func__);
 }
 
+static void  update_hardware_info_sda845(struct hardware_info *hw_info, const char *snd_card_name)
+{
+    if (!strncmp(snd_card_name, "sda845-tavil-i2s-snd-card", sizeof("sda845-tavil-i2s-snd-card"))) {
+        strlcpy(hw_info->type, " mtp", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "sda845", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        hw_info->is_stereo_spkr = false;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    } else {
+        ALOGW("%s: Not a sda845 device", __func__);
+    }
+}
+
 static void  update_hardware_info_sdx(struct hardware_info *hw_info __unused, const char *snd_card_name __unused)
 {
     ALOGW("%s: Not a sdx device", __func__);
@@ -592,6 +606,9 @@
     } else if (strstr(snd_card_name, "pahu")) {
         ALOGV("MSMNILE - variant soundcard");
         update_hardware_info_msmnile(hw_info, snd_card_name);
+    } else if (strstr(snd_card_name, "sda845")) {
+        ALOGV("SDA845 - variant soundcard");
+        update_hardware_info_sda845(hw_info, snd_card_name);
     } else {
         ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
         free(hw_info);
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 96b817f..475e438 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1337,7 +1337,9 @@
         !strncmp(snd_card_name, "apq8096-tasha-i2c-snd-card",
                  sizeof("apq8096-tasha-i2c-snd-card")) ||
         !strncmp(snd_card_name, "sdx-tavil-i2s-snd-card",
-                 sizeof("sdx-tavil-i2s-snd-card"))){
+                 sizeof("sdx-tavil-i2s-snd-card")) ||
+        !strncmp(snd_card_name, "sda845-tavil-i2s-snd-card",
+                 sizeof("sda845-tavil-i2s-snd-card"))) {
         plat_data->is_i2s_ext_modem = true;
     }
     ALOGV("%s, is_i2s_ext_modem:%d soundcard name is %s",__func__,
@@ -2299,8 +2301,10 @@
     property_get("ro.baseband", baseband, "");
     if ((!strncmp("apq8084", platform, sizeof("apq8084")) ||
         !strncmp("msm8996", platform, sizeof("msm8996")) ||
-        !strncmp("sdx", platform, sizeof("sdx"))) &&
-        !strncmp("mdm", baseband, (sizeof("mdm")-1))) {
+        !strncmp("sdx", platform, sizeof("sdx")) ||
+        !strncmp("sdm845", platform, sizeof("sdm845"))) &&
+        ( !strncmp("mdm", baseband, (sizeof("mdm")-1)) ||
+          !strncmp("sdx", baseband, (sizeof("sdx")-1)))) {
          my_data->csd = open_csd_client(my_data->is_i2s_ext_modem);
     } else {
          my_data->csd = NULL;
diff --git a/qahw/Makefile.am b/qahw/Makefile.am
index 1375157..b78c9b7 100644
--- a/qahw/Makefile.am
+++ b/qahw/Makefile.am
@@ -13,6 +13,10 @@
 libqahwwrapper_la_SOURCES = src/qahw.c \
                      src/qahw_effect.c
 
+if SVA_AUDIO_CONCURRENCY
+AM_CFLAGS += -DSVA_AUDIO_CONC
+endif
+
 libqahwwrapper_la_CFLAGS  = $(AM_CFLAGS)
 libqahwwrapper_la_CFLAGS += -include stddef.h
 libqahwwrapper_la_CFLAGS += -Dstrlcpy=g_strlcpy $(GLIB_CFLAGS) -include glib.h
diff --git a/qahw/configure.ac b/qahw/configure.ac
index 04fde19..5bd3a22 100644
--- a/qahw/configure.ac
+++ b/qahw/configure.ac
@@ -29,6 +29,7 @@
 AC_PROG_MAKE_SET
 PKG_PROG_PKG_CONFIG
 
+AM_CONDITIONAL([SVA_AUDIO_CONCURRENCY],[test x$BOARD_SUPPORTS_SVA_AUDIO_CONCURRENCY = xtrue])
 AC_ARG_WITH([glib],
       AC_HELP_STRING([--with-glib],
          [enable glib, Build against glib. Use this when building for HLOS systems which use glib]))
diff --git a/qahw/src/qahw.c b/qahw/src/qahw.c
index 91fc5bf..d03a570 100644
--- a/qahw/src/qahw.c
+++ b/qahw/src/qahw.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016-2018, 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
@@ -37,6 +37,7 @@
 #include <cutils/list.h>
 
 #include <hardware/audio.h>
+#include <hardware/sound_trigger.h>
 #include "qahw.h"
 
 #define NO_ERROR 0
@@ -113,6 +114,7 @@
 static struct listnode qahw_module_list;
 static int qahw_list_count;
 static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
+sound_trigger_hw_device_t *st_hw_device = NULL;
 
 
 /** Start of internal functions */
@@ -1776,6 +1778,45 @@
     return QAHW_MODULE_API_VERSION_CURRENT;
 }
 
+/* Load AHAL module to run audio and sva concurrency */
+static void load_st_hal()
+{
+#ifdef SVA_AUDIO_CONC
+    int rc = -EINVAL;
+    const hw_module_t* module = NULL;
+
+    rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", &module);
+    if (rc) {
+        ALOGE("%s: AHAL Loading failed %d", __func__, rc);
+        goto error;
+    }
+
+    rc = sound_trigger_hw_device_open(module, &st_hw_device);
+    if (rc) {
+        ALOGE("%s: AHAL Device open failed %d", __func__, rc);
+        st_hw_device = NULL;
+    }
+error:
+    return;
+#else
+    return;
+#endif /*SVA_AUDIO_CONC*/
+}
+
+static void unload_st_hal()
+{
+#ifdef SVA_AUDIO_CONC
+    if (st_hw_device == NULL) {
+        ALOGE("%s: audio device is NULL",__func__);
+        return;
+    }
+    sound_trigger_hw_device_close(st_hw_device);
+    st_hw_device = NULL;
+#else
+    return;
+#endif /*SVA_AUDIO_CONC*/
+}
+
 /* convenience API for opening and closing an audio HAL module */
 
 qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
@@ -1867,7 +1908,7 @@
 
     /* Add module list to global module list */
     list_add_tail(&qahw_module_list, &qahw_module->module_list);
-
+    load_st_hal();
 
 error_exit:
     pthread_mutex_unlock(&qahw_module_init_lock);
@@ -1924,6 +1965,7 @@
                "is not closed", __func__);
         rc = -EINVAL;
     }
+    unload_st_hal();
 
 error_exit:
     pthread_mutex_unlock(&qahw_module_init_lock);