Merge "Adding Audio HAL V5: Direction API"
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..d65f614
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,5 @@
+# Default code reviewers picked from top 3 or more developers.
+# Please update this list if you find better candidates.
+hunga@google.com
+krocard@google.com
+elaurent@google.com
diff --git a/hal/Android.mk b/hal/Android.mk
index 236ed11..7f93710 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -197,7 +197,6 @@
     LOCAL_SRC_FILES += audio_extn/sndmonitor.c
 endif
 
-
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_USB_SERVICE_INTERVAL)), true)
     LOCAL_CFLAGS += -DUSB_SERVICE_INTERVAL_ENABLED
 endif
@@ -215,6 +214,10 @@
     LOCAL_CFLAGS += -DBG_CODEC_CAL
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DYNAMIC_ECNS)),true)
+    LOCAL_CFLAGS += -DDYNAMIC_ECNS_ENABLED
+endif
+
 LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhwbinder libutils android.hardware.power@1.2 liblog
 
 LOCAL_SRC_FILES += audio_perf.cpp
diff --git a/hal/audio_extn/maxxaudio.c b/hal/audio_extn/maxxaudio.c
index cc5070c..69c4606 100644
--- a/hal/audio_extn/maxxaudio.c
+++ b/hal/audio_extn/maxxaudio.c
@@ -43,7 +43,9 @@
 
 #define MA_QDSP_PARAM_INIT      "maxxaudio_qdsp_initialize"
 #define MA_QDSP_PARAM_DEINIT    "maxxaudio_qdsp_uninitialize"
+#define MA_QDSP_IS_FEATURE_USED "maxxaudio_qdsp_is_feature_supported"
 #define MA_QDSP_SET_LR_SWAP     "maxxaudio_qdsp_set_lr_swap"
+#define MA_QDSP_SET_ORIENTATION "maxxaudio_qdsp_set_orientation"
 #define MA_QDSP_SET_MODE        "maxxaudio_qdsp_set_sound_mode"
 #define MA_QDSP_SET_VOL         "maxxaudio_qdsp_set_volume"
 #define MA_QDSP_SET_VOLT        "maxxaudio_qdsp_set_volume_table"
@@ -87,6 +89,8 @@
     MA_CMD_VOL,
     MA_CMD_SWAP_ENABLE,
     MA_CMD_SWAP_DISABLE,
+    MA_CMD_ROTATE_ENABLE,
+    MA_CMD_ROTATE_DISABLE,
     MA_CMD_SOFT_MUTE_ENABLE,
     MA_CMD_SOFT_MUTE_DISABLE,
 } ma_cmd_t;
@@ -120,9 +124,14 @@
 
 typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t *);
 
+typedef bool (*ma_is_feature_used_t)(ma_audio_cal_handle_t, const char *);
+
 typedef bool (*ma_set_lr_swap_t)(ma_audio_cal_handle_t,
                                  const struct ma_audio_cal_settings *, bool);
 
+typedef bool (*ma_set_orientation_t)(ma_audio_cal_handle_t,
+                                     const struct ma_audio_cal_settings *, int);
+
 typedef bool (*ma_set_sound_mode_t)(ma_audio_cal_handle_t,
                                     const struct ma_audio_cal_settings *,
                                     unsigned int);
@@ -144,12 +153,16 @@
     pthread_mutex_t lock;
     ma_param_init_t          ma_param_init;
     ma_param_deinit_t        ma_param_deinit;
+    ma_is_feature_used_t     ma_is_feature_used;
     ma_set_lr_swap_t         ma_set_lr_swap;
+    ma_set_orientation_t     ma_set_orientation;
     ma_set_sound_mode_t      ma_set_sound_mode;
     ma_set_volume_t          ma_set_volume;
     ma_set_volume_table_t    ma_set_volume_table;
     ma_set_param_t           ma_set_param;
     bool speaker_lr_swap;
+    bool orientation_used;
+    int dispaly_orientation;
 };
 
 ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL;
@@ -172,6 +185,13 @@
                                    audio_cal_settings, swap);
 }
 
+static bool ma_set_orientation_l(
+    const struct ma_audio_cal_settings *audio_cal_settings, int orientation)
+{
+    return my_data->ma_set_orientation(g_ma_audio_cal_handle,
+                                   audio_cal_settings, orientation);
+}
+
 static bool ma_set_sound_mode_l(
     const struct ma_audio_cal_settings *audio_cal_settings, int sound_mode)
 {
@@ -302,6 +322,24 @@
                         ALOGE("ma_set_lr_swap_l disable returned with error.");
                     break;
 
+                case MA_CMD_ROTATE_ENABLE:
+                    if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+                        ret = ma_set_orientation_l(&ma_cal, my_data->dispaly_orientation);
+                        if (ret)
+                            ALOGV("ma_set_orientation_l %d returned with success.", my_data->dispaly_orientation);
+                        else
+                            ALOGE("ma_set_orientation_l %d returned with error.", my_data->dispaly_orientation);
+                    }
+                    break;
+
+                case MA_CMD_ROTATE_DISABLE:
+                    ret = ma_set_orientation_l(&ma_cal, 0);
+                    if (ret)
+                        ALOGV("ma_set_orientation_l 0 returned with success.");
+                    else
+                        ALOGE("ma_set_orientation_l 0 returned with error.");
+                    break;
+
                 case MA_CMD_SOFT_MUTE_ENABLE:
                     if (usecase->id == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) break;
 
@@ -363,6 +401,14 @@
         check_and_send_all_audio_cal(adev, MA_CMD_SWAP_DISABLE);
 }
 
+static void ma_set_rotation_l(struct audio_device *adev, int orientation)
+{
+    if (orientation != 0)
+        check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_ENABLE);
+    else
+        check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_DISABLE);
+}
+
 static void ma_support_usb(bool enable, int card)
 {
     char path[128];
@@ -457,6 +503,18 @@
              goto error;
          }
 
+        my_data->ma_is_feature_used = (ma_is_feature_used_t)dlsym(my_data->waves_handle,
+                                    MA_QDSP_IS_FEATURE_USED);
+        if (!my_data->ma_is_feature_used) {
+            ALOGV("%s: dlsym error %s for ma_is_feature_used", __func__, dlerror());
+        }
+
+        my_data->ma_set_orientation = (ma_set_orientation_t)dlsym(my_data->waves_handle,
+                                        MA_QDSP_SET_ORIENTATION);
+        if (!my_data->ma_set_orientation) {
+            ALOGV("%s: dlsym error %s for ma_set_orientation", __func__, dlerror());
+        }
+
          my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
                                     MA_QDSP_SET_LR_SWAP);
          if (!my_data->ma_set_lr_swap) {
@@ -555,6 +613,12 @@
     }
 
     my_data->speaker_lr_swap = false;
+    my_data->orientation_used = false;
+    my_data->dispaly_orientation = 0;
+
+    if (g_ma_audio_cal_handle && my_data->ma_is_feature_used) {
+        my_data->orientation_used = my_data->ma_is_feature_used(g_ma_audio_cal_handle, "SET_ORIENTATION");
+    }
 
     return;
 
@@ -657,10 +721,18 @@
     pthread_mutex_lock(&my_data->lock);
 
     if (is_active()) {
-        if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER)
-            ma_set_swap_l(usecase->stream.out->dev, my_data->speaker_lr_swap);
-        else
-            ma_set_swap_l(usecase->stream.out->dev, false);
+
+        if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+            if (my_data->orientation_used)
+                ma_set_rotation_l(usecase->stream.out->dev, my_data->dispaly_orientation);
+            else
+                ma_set_swap_l(usecase->stream.out->dev, my_data->speaker_lr_swap);
+        } else {
+            if (my_data->orientation_used)
+                ma_set_rotation_l(usecase->stream.out->dev, 0);
+            else
+                ma_set_swap_l(usecase->stream.out->dev, false);
+        }
 
         ALOGV("%s: send volume table === Start", __func__);
         for (i = 0; i < STREAM_MAX_TYPES; i++)
@@ -706,7 +778,12 @@
             my_data->speaker_lr_swap = false;
             break;
         }
-        ma_set_swap_l(adev, my_data->speaker_lr_swap);
+        my_data->dispaly_orientation = val;
+
+        if (my_data->orientation_used)
+            ma_set_rotation_l(adev, my_data->dispaly_orientation);
+        else
+            ma_set_swap_l(adev, my_data->speaker_lr_swap);
     }
 
     // check connect status
diff --git a/hal/audio_extn/sndmonitor.c b/hal/audio_extn/sndmonitor.c
index 2e8fd43..85a8c94 100644
--- a/hal/audio_extn/sndmonitor.c
+++ b/hal/audio_extn/sndmonitor.c
@@ -194,7 +194,8 @@
         if ((strncasecmp(card_id, "msm", 3) != 0) &&
             (strncasecmp(card_id, "sdm", 3) != 0) &&
             (strncasecmp(card_id, "sdc", 3) != 0) &&
-            (strncasecmp(card_id, "apq", 3) != 0)) {
+            (strncasecmp(card_id, "apq", 3) != 0) &&
+            (strncasecmp(card_id, "sm8150", 6) != 0)) {
             ALOGW("Skip over non-ADSP snd card %s", card_id);
             continue;
         }
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 183f0b0..00cf661 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -807,6 +807,147 @@
     return 0;
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
+                          struct stream_in *in,
+                          struct audio_effect_config effect_config,
+                          unsigned int param_value)
+{
+    char mixer_ctl_name[] = "Audio Effect";
+    long set_values[6];
+
+    struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get mixer ctl - %s",
+               __func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+
+    set_values[0] = 1; //0:Rx 1:Tx
+    set_values[1] = in->app_type_cfg.app_type;
+    set_values[2] = (long)effect_config.module_id;
+    set_values[3] = (long)effect_config.instance_id;
+    set_values[4] = (long)effect_config.param_id;
+    set_values[5] = param_value;
+
+    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+    return 0;
+
+}
+
+static int update_effect_param_ecns(struct audio_usecase *usecase,
+                               unsigned int module_id, int effect_type,
+                               unsigned int *param_value)
+{
+    int ret = 0;
+    struct audio_effect_config other_effect_config;
+    struct stream_in *in = NULL;
+
+    if (!usecase)
+        return -EINVAL;
+
+    in = usecase->stream.in;
+
+    /* Get the effect config data of the other effect */
+    ret = platform_get_effect_config_data(usecase->in_snd_device,
+                                          &other_effect_config,
+                                          effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
+    if (ret < 0) {
+        ALOGE("%s Failed to get effect params %d", __func__, ret);
+        return ret;
+    }
+
+    if (module_id == other_effect_config.module_id) {
+            //Same module id for AEC/NS. Values need to be combined
+            if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
+                ((effect_type == EFFECT_NS) && (in->enable_aec)))
+                *param_value |= other_effect_config.param_value;
+    }
+
+    return ret;
+}
+
+static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
+                                   int effect_type, bool enable)
+{
+    struct audio_effect_config effect_config;
+    struct audio_usecase *usecase = NULL;
+    int ret = 0;
+    unsigned int param_value = 0;
+
+    if (!in) {
+        ALOGE("%s: Invalid input stream", __func__);
+        return -EINVAL;
+    }
+
+    ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
+
+    usecase = get_usecase_from_list(adev, in->usecase);
+
+    ret = platform_get_effect_config_data(usecase->in_snd_device,
+                                           &effect_config, effect_type);
+    if (ret < 0) {
+        ALOGE("%s Failed to get module id %d", __func__, ret);
+        return ret;
+    }
+    ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
+           __func__, effect_config.module_id, in->app_type_cfg.app_type,
+          usecase->id, usecase->in_snd_device);
+
+    if (enable)
+        param_value = effect_config.param_value;
+
+    /*Special handling for AEC & NS effects Param values need to be
+      updated if module ids are same*/
+
+    if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
+        ret = update_effect_param_ecns(usecase, effect_config.module_id,
+                                       effect_type, &param_value);
+        if (ret < 0)
+            return ret;
+    }
+
+    ret = send_effect_enable_disable_mixer_ctl(adev, in,
+                                               effect_config, param_value);
+
+    return ret;
+}
+
+static int check_and_enable_effect(struct audio_device *adev)
+{
+    int ret = 0;
+
+    struct listnode *node;
+    struct stream_in *in = NULL;
+
+    list_for_each(node, &adev->usecase_list)
+    {
+        struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+            in = usecase->stream.in;
+
+            if (in->standby)
+                continue;
+
+            if (in->enable_aec) {
+                ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
+            }
+
+            if (in->enable_ns &&
+                in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+                ret = enable_disable_effect(adev, in, EFFECT_NS, true);
+            }
+        }
+    }
+
+    return ret;
+}
+#else
+#define enable_disable_effect(w, x, y, z) -ENOSYS
+#define check_and_enable_effect(x) -ENOSYS
+#endif
+
 /*
   legend:
   uc - existing usecase
@@ -1032,6 +1173,10 @@
         if (usecase->type != PCM_PLAYBACK &&
                 usecase != uc_info &&
                 usecase->in_snd_device != snd_device &&
+                ((uc_info->type == VOICE_CALL &&
+                  usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
+                 platform_check_backends_match(snd_device,\
+                                              usecase->in_snd_device)) &&
                 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
             ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
                   __func__, use_case_table[usecase->id],
@@ -1543,6 +1688,11 @@
 
     audio_extn_ma_set_device(usecase);
 
+    /* If input stream is already running the effect needs to be
+       applied on the new input device that's being enabled here.  */
+    if (in_snd_device != SND_DEVICE_NONE)
+        check_and_enable_effect(adev);
+
     /* Applicable only on the targets that has external modem.
      * Enable device command should be sent to modem only after
      * enabling voice call mixer controls
@@ -1708,6 +1858,7 @@
         }
     }
     register_in_stream(in);
+    check_and_enable_effect(adev);
     audio_streaming_hint_end();
     audio_extn_perf_lock_release();
     ALOGV("%s: exit", __func__);
@@ -3954,6 +4105,8 @@
     effect_descriptor_t desc;
 
     status = (*effect)->get_descriptor(effect, &desc);
+    ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
+
     if (status != 0)
         return status;
 
@@ -3978,14 +4131,18 @@
                     select_devices(adev, usecase->id);
             }
         }
-        if (!in->standby)
+        if (!in->standby
+            && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
             select_devices(in->dev, in->usecase);
     }
     if (in->enable_ns != enable &&
             (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
         in->enable_ns = enable;
-        if (!in->standby)
-            select_devices(in->dev, in->usecase);
+        if (!in->standby) {
+            if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
+                || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
+                select_devices(in->dev, in->usecase);
+        }
     }
     pthread_mutex_unlock(&in->dev->lock);
     pthread_mutex_unlock(&in->lock);
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 56220e1..7d35ff5 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -81,6 +81,8 @@
 #define TOSTRING_(x) #x
 #define TOSTRING(x) TOSTRING_(x)
 
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
 };
@@ -301,6 +303,34 @@
     [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
 };
 
+static struct audio_effect_config \
+               effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_COUNT] = {
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FLUENCE_PROV2,  0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_AEC] = \
+                                      {TX_VOICE_DM_FV5_BROADSIDE, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_NS] = \
+                                      {TX_VOICE_DM_FV5_BROADSIDE, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+};
+
 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
 static int acdb_device_table[SND_DEVICE_MAX] = {
     [SND_DEVICE_NONE] = -1,
@@ -1416,6 +1446,35 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (effect_config == NULL) {
+        ALOGE("%s: Invalid effect_config", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s: snd_device = %d module_id = %d",
+          __func__, snd_device,
+          effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+    *effect_config = effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type];
+
+done:
+    return ret;
+}
+
 void platform_add_operator_specific_device(snd_device_t snd_device,
                                            const char *operator,
                                            const char *mixer_path,
@@ -1499,6 +1558,27 @@
         }
     }
     return key;
+
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+           effect_config.instance_id, effect_config.param_id,
+           effect_config.param_value);
+    effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+done:
+    return ret;
 }
 
 int platform_get_default_app_type_v2(void *platform, usecase_type_t type, int *app_type)
@@ -1930,6 +2010,139 @@
     return snd_device;
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in __unused,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE) {
+        switch(AUDIO_DEVICE_BIT_IN | in_device) {
+            case AUDIO_DEVICE_IN_BACK_MIC:
+                if (my_data->fluence_in_spkr_mode) {
+                    if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                        snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                    } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                        if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                            snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                        else
+                            snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                    }
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+                break;
+            case AUDIO_DEVICE_IN_BUILTIN_MIC:
+                if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+                break;
+            default:
+                ALOGE("%s: Unsupported in_device %#x", __func__, in_device);
+                break;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    }
+
+    return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE &&
+        in->enable_aec &&
+        in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               in->enable_aec) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
+                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
+                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, false, out_device);
+    } else
+        platform_set_echo_reference(adev, false, out_device);
+
+    return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
 snd_device_t platform_get_input_snd_device(void *platform,
                                            struct stream_in *in,
                                            audio_devices_t out_device)
@@ -2056,85 +2269,10 @@
               (mode == AUDIO_MODE_IN_COMMUNICATION)) {
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
+
         if (in) {
-            if (my_data->fluence_type != FLUENCE_NONE &&
-                in->enable_aec &&
-                in->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
-                        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       in->enable_aec) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
-                        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       in->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
-                        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, false, out_device);
-            } else
-                platform_set_echo_reference(adev, false, out_device);
+            snd_device = get_snd_device_for_voice_comm(my_data, in, 
+                                                       out_device, in_device);
         }
     } else if (source == AUDIO_SOURCE_FM_TUNER) {
         snd_device = SND_DEVICE_IN_CAPTURE_FM;
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 9913322..f3dbc3d 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -250,6 +250,11 @@
 
 #define AUDIO_MAKE_STRING_FROM_ENUM(X)   { #X, X }
 
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 /* CSD-CLIENT related functions */
 typedef int (*init_t)();
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 481b57d..f03356b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -72,6 +72,8 @@
 #define TOSTRING_(x) #x
 #define TOSTRING(x) TOSTRING_(x)
 
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
 struct audio_block_header
 {
     int reserved;
@@ -368,6 +370,32 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = "camcorder-mic",
     [SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = "camcorder-mic",
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic",
+    [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic",
+    [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
+};
+
+static struct audio_effect_config \
+                  effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_COUNT] = {
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FLUENCE_PROV2,  0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = \
+                                      {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
 };
 
 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -491,6 +519,8 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = 61,
     [SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = 61,
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61,
+    [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129,
+    [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129,
 };
 
 // Platform specific backend bit width table
@@ -627,6 +657,8 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)},
     /* For legacy xml file parsing */
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -1342,6 +1374,8 @@
     hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_STEREO] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_DMIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_DMIC_TMUS] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_NS] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP] = strdup("SLIMBUS_0_TX");
@@ -2067,6 +2101,57 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (effect_config == NULL) {
+        ALOGE("%s: Invalid effect_config", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s: snd_device = %d module_id = %d",
+            __func__, snd_device, effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+    *effect_config = effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type];
+
+done:
+    return ret;
+}
+
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+        ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+            __func__, snd_device, effect_type);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+           effect_config.instance_id, effect_config.param_id,
+           effect_config.param_value);
+    effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+
+done:
+    return ret;
+}
+
 void platform_add_operator_specific_device(snd_device_t snd_device,
                                            const char *operator,
                                            const char *mixer_path,
@@ -2865,6 +2950,126 @@
     return snd_device;
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in __unused,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_DISABLE) {
+        switch(AUDIO_DEVICE_BIT_IN | in_device) {
+            case AUDIO_DEVICE_IN_BACK_MIC:
+                if (my_data->fluence_in_spkr_mode) {
+                    if ((my_data->fluence_type & FLUENCE_PRO_ENABLE) &&
+                        (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                        snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                    } else if (((my_data->fluence_type & FLUENCE_PRO_ENABLE) ||
+                               (my_data->fluence_type & FLUENCE_ENABLE)) &&
+                               (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                            snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                    }
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+                break;
+            case AUDIO_DEVICE_IN_BUILTIN_MIC:
+                if (((my_data->fluence_type & FLUENCE_PRO_ENABLE) ||
+                    (my_data->fluence_type & FLUENCE_ENABLE)) &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                    adev->acdb_settings |= DMIC_FLAG;
+                } else
+                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+                break;
+            default:
+                ALOGE("%s: Unsupported in_device %#x", __func__, in_device);
+                break;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    }
+
+    return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  struct stream_in *in,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (in->enable_aec &&
+            in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode &&
+                    my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
+        } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (in->enable_aec) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode &&
+                    my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+            } else {
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+            } else {
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+            }
+       } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+           snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
+       } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
+           snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+       }
+       platform_set_echo_reference(adev, true, out_device);
+    } else if (in->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode &&
+                    my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+            }
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if (my_data->fluence_in_voice_comm &&
+                    (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+            } else {
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+            }
+        }
+    }
+
+    return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
 snd_device_t platform_get_input_snd_device(void *platform,
                                            struct stream_in *in,
                                            audio_devices_t out_device)
@@ -3091,70 +3296,9 @@
                 !audio_extn_usb_is_capture_supported())) {
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
         }
+
         if (in) {
-            if (in->enable_aec &&
-                    in->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode &&
-                            my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
-                } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
-                    snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (in->enable_aec) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode &&
-                            my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
-                    } else {
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
-                    } else {
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
-                    }
-               } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                   snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
-               } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
-                   snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-               }
-               platform_set_echo_reference(adev, true, out_device);
-            } else if (in->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode &&
-                            my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
-                    }
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if (my_data->fluence_in_voice_comm &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
-                    } else {
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
-                    }
-                }
-            }
+            snd_device = get_snd_device_for_voice_comm(my_data, in, out_device, in_device);
         }
     } else if (source == AUDIO_SOURCE_DEFAULT) {
         goto exit;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index f6c5a58..a885f27 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -190,6 +190,8 @@
     SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE,
     SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE,
     SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT,
+    SND_DEVICE_IN_SPEAKER_QMIC_NS,
+    SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -343,6 +345,11 @@
 #define HFP_ASM_RX_TX 24
 #endif
 
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 #define LIB_MDM_DETECT "libmdmdetect.so"
 
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 3cd2b8d..5e5b662 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -27,6 +27,20 @@
 #define SAMPLE_RATE_11025 11025
 #define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
 
+typedef enum {
+    EFFECT_NONE = 0,
+    EFFECT_AEC,
+    EFFECT_NS,
+    EFFECT_COUNT
+} effect_type_t;
+
+struct audio_effect_config {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t param_id;
+    uint32_t param_value;
+};
+
 struct amp_db_and_gain_table {
     float amp;
     float db;
@@ -56,6 +70,12 @@
 int platform_get_snd_device_index(char *snd_device_index_name);
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
 int platform_get_snd_device_acdb_id(snd_device_t snd_device);
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type);
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type);
 int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
 int platform_send_audio_calibration_v2(void *platform, struct audio_usecase *usecase,
                                        int app_type, int sample_rate);
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 0695592..233e120 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -38,6 +38,9 @@
 typedef enum {
     ROOT,
     ACDB,
+    MODULE,
+    AEC,
+    NS,
     PCM_ID,
     BACKEND_NAME,
     CONFIG_PARAMS,
@@ -56,6 +59,9 @@
 typedef void (* section_process_fn)(const XML_Char **attr);
 
 static void process_acdb_id(const XML_Char **attr);
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type);
+static void process_effect_aec(const XML_Char **attr);
+static void process_effect_ns(const XML_Char **attr);
 static void process_pcm_id(const XML_Char **attr);
 static void process_backend_name(const XML_Char **attr);
 static void process_config_params(const XML_Char **attr);
@@ -71,6 +77,8 @@
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
     [ACDB] = process_acdb_id,
+    [AEC] = process_effect_aec,
+    [NS] = process_effect_ns,
     [PCM_ID] = process_pcm_id,
     [BACKEND_NAME] = process_backend_name,
     [CONFIG_PARAMS] = process_config_params,
@@ -185,6 +193,11 @@
  * ...
  * ...
  * </acdb_ids>
+ * <module_ids>
+ * <device name="???" module_id="???"/>
+ * ...
+ * ...
+ * </module_ids>
  * <backend_names>
  * <device name="???" backend="???"/>
  * ...
@@ -216,6 +229,77 @@
 {
 }
 
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type)
+{
+    int index;
+    struct audio_effect_config effect_config;
+
+    if (strncmp(attr[0], "name", strlen("name")) != 0) {
+        ALOGE("%s: 'name' not found, no MODULE ID set!", __func__);
+        goto done;
+    }
+
+    index = platform_get_snd_device_index((char *)attr[1]);
+    if (index < 0) {
+        ALOGE("%s: Device %s in platform info xml not found, no MODULE ID set!",
+              __func__, attr[1]);
+        goto done;
+    }
+
+    if (strncmp(attr[2], "module_id", strlen("module_id")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no module_id, no MODULE ID set!",
+              __func__, attr[2]);
+        goto done;
+    }
+
+    if (strncmp(attr[4], "instance_id", strlen("instance_id")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no instance_id, no INSTANCE ID set!",
+              __func__, attr[4]);
+        goto done;
+    }
+
+    if (strncmp(attr[6], "param_id", strlen("param_id")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no param_id, no PARAM ID set!",
+              __func__, attr[6]);
+        goto done;
+    }
+
+    if (strncmp(attr[8], "param_value", strlen("param_value")) != 0) {
+        ALOGE("%s: Device %s in platform info xml has no param_value, no PARAM VALUE set!",
+              __func__, attr[8]);
+        goto done;
+    }
+
+    effect_config = (struct audio_effect_config){strtol((char *)attr[3], NULL, 0),
+                                                 strtol((char *)attr[5], NULL, 0),
+                                                 strtol((char *)attr[7], NULL, 0),
+                                                 strtol((char *)attr[9], NULL, 0)};
+
+
+    if (platform_set_effect_config_data(index, effect_config, effect_type) < 0) {
+        ALOGE("%s: Effect = %d Device %s, MODULE/INSTANCE/PARAM ID %u %u %u %u was not set!",
+              __func__, effect_type, attr[1], effect_config.module_id,
+              effect_config.instance_id, effect_config.param_id,
+              effect_config.param_value);
+        goto done;
+    }
+
+done:
+    return;
+}
+
+static void process_effect_aec(const XML_Char **attr)
+{
+    process_audio_effect(attr, EFFECT_AEC);
+    return;
+}
+
+static void process_effect_ns(const XML_Char **attr)
+{
+    process_audio_effect(attr, EFFECT_NS);
+    return;
+}
+
 /* mapping from usecase to pcm dev id */
 static void process_pcm_id(const XML_Char **attr)
 {
@@ -717,6 +801,8 @@
     if (my_data.do_full_parse) {
         if (strcmp(tag_name, "acdb_ids") == 0) {
             section = ACDB;
+        } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) {
+            section = MODULE;
         } else if (strcmp(tag_name, "pcm_ids") == 0) {
             section = PCM_ID;
         } else if (strcmp(tag_name, "backend_names") == 0) {
@@ -736,8 +822,9 @@
         } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
             section = ACDB_METAINFO_KEY;
         } else if (strcmp(tag_name, "device") == 0) {
-            if ((section != ACDB) && (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
-                ALOGE("device tag only supported for acdb/backend names");
+            if ((section != ACDB) && (section != AEC) && (section != NS) &&
+                (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
+                ALOGE("device tag only supported for acdb/backend/aec/ns/operator_specific names");
                 return;
             }
 
@@ -814,6 +901,20 @@
             section_process_fn fn = section_table[MIC_INFO];
             fn(attr);
         }
+        else if (strncmp(tag_name, "aec", strlen("aec")) == 0) {
+            if (section != MODULE) {
+                ALOGE("aec tag only supported with MODULE section");
+                return;
+            }
+            section = AEC;
+        }
+        else if (strncmp(tag_name, "ns", strlen("ns")) == 0) {
+            if (section != MODULE) {
+                ALOGE("ns tag only supported with MODULE section");
+                return;
+            }
+            section = NS;
+        }
     } else {
         if(strcmp(tag_name, "config_params") == 0) {
             section = CONFIG_PARAMS;
@@ -835,6 +936,12 @@
 {
     if (strcmp(tag_name, "acdb_ids") == 0) {
         section = ROOT;
+    } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) {
+        section = ROOT;
+    } else if (strncmp(tag_name, "aec", strlen("aec")) == 0) {
+        section = MODULE;
+    } else if (strncmp(tag_name, "ns", strlen("ns")) == 0) {
+        section = MODULE;
     } else if (strcmp(tag_name, "pcm_ids") == 0) {
         section = ROOT;
     } else if (strcmp(tag_name, "backend_names") == 0) {