Merge "configs: rename vendor properties"
diff --git a/configs/kona/audio_configs.xml b/configs/kona/audio_configs.xml
index fa07ca2..8c24bb2 100644
--- a/configs/kona/audio_configs.xml
+++ b/configs/kona/audio_configs.xml
@@ -92,6 +92,7 @@
         <flag name="incall_music_enabled" value="true" />
         <flag name="keep_alive_enabled" value="true" />
         <flag name="kpi_optimize_enabled" value="true" />
+        <flag name="maxx_audio_enabled" value="false" />
         <flag name="receiver_aided_stereo" value="true" />
         <flag name="snd_monitor_enabled" value="true" />
         <flag name="source_track_enabled" value="true" />
diff --git a/configs/msm8937/audio_configs.xml b/configs/msm8937/audio_configs.xml
index e221be7..ed3ed8d 100644
--- a/configs/msm8937/audio_configs.xml
+++ b/configs/msm8937/audio_configs.xml
@@ -92,6 +92,7 @@
         <flag name="incall_music_enabled" value="false" />
         <flag name="keep_alive_enabled" value="false" />
         <flag name="kpi_optimize_enabled" value="true" />
+        <flag name="maxx_audio_enabled" value="false" />
         <flag name="receiver_aided_stereo" value="false" />
         <flag name="snd_monitor_enabled" value="true" />
         <flag name="source_track_enabled" value="true" />
diff --git a/configs/msmnile/audio_configs.xml b/configs/msmnile/audio_configs.xml
index fa07ca2..8c24bb2 100644
--- a/configs/msmnile/audio_configs.xml
+++ b/configs/msmnile/audio_configs.xml
@@ -92,6 +92,7 @@
         <flag name="incall_music_enabled" value="true" />
         <flag name="keep_alive_enabled" value="true" />
         <flag name="kpi_optimize_enabled" value="true" />
+        <flag name="maxx_audio_enabled" value="false" />
         <flag name="receiver_aided_stereo" value="true" />
         <flag name="snd_monitor_enabled" value="true" />
         <flag name="source_track_enabled" value="true" />
diff --git a/configs/msmnile/audio_configs_stock.xml b/configs/msmnile/audio_configs_stock.xml
index b9ecf45..6414675 100644
--- a/configs/msmnile/audio_configs_stock.xml
+++ b/configs/msmnile/audio_configs_stock.xml
@@ -57,6 +57,7 @@
         <flag name="incall_music_enabled" value="true" />
         <flag name="keep_alive_enabled" value="false" />
         <flag name="kpi_optimize_enabled" value="false" />
+        <flag name="maxx_audio_enabled" value="true" />
         <flag name="receiver_aided_stereo" value="false" />
         <flag name="record_play_concurrency" value="false" />
         <flag name="snd_monitor_enabled" value="true" />
diff --git a/configs/sdm660/audio_configs.xml b/configs/sdm660/audio_configs.xml
index 853f7e7..3688697 100644
--- a/configs/sdm660/audio_configs.xml
+++ b/configs/sdm660/audio_configs.xml
@@ -92,6 +92,7 @@
         <flag name="incall_music_enabled" value="false" />
         <flag name="keep_alive_enabled" value="false" />
         <flag name="kpi_optimize_enabled" value="true" />
+        <flag name="maxx_audio_enabled" value="false" />
         <flag name="receiver_aided_stereo" value="true" />
         <flag name="snd_monitor_enabled" value="true" />
         <flag name="source_track_enabled" value="true" />
diff --git a/configs/sdm710/audio_configs.xml b/configs/sdm710/audio_configs.xml
index 0410f4b..6a6fb7d 100644
--- a/configs/sdm710/audio_configs.xml
+++ b/configs/sdm710/audio_configs.xml
@@ -92,6 +92,7 @@
         <flag name="incall_music_enabled" value="false" />
         <flag name="keep_alive_enabled" value="false" />
         <flag name="kpi_optimize_enabled" value="true" />
+        <flag name="maxx_audio_enabled" value="false" />
         <flag name="receiver_aided_stereo" value="true" />
         <flag name="snd_monitor_enabled" value="true" />
         <flag name="source_track_enabled" value="true" />
diff --git a/configs/sdm845/audio_configs.xml b/configs/sdm845/audio_configs.xml
index 95b7d97..4b0159d 100644
--- a/configs/sdm845/audio_configs.xml
+++ b/configs/sdm845/audio_configs.xml
@@ -92,6 +92,7 @@
         <flag name="incall_music_enabled" value="false" />
         <flag name="keep_alive_enabled" value="false" />
         <flag name="kpi_optimize_enabled" value="true" />
+        <flag name="maxx_audio_enabled" value="false" />
         <flag name="receiver_aided_stereo" value="true" />
         <flag name="snd_monitor_enabled" value="true" />
         <flag name="source_track_enabled" value="true" />
diff --git a/hal/ahal_config_helper.cpp b/hal/ahal_config_helper.cpp
index 753d8a8..e46b8f3 100644
--- a/hal/ahal_config_helper.cpp
+++ b/hal/ahal_config_helper.cpp
@@ -105,6 +105,7 @@
         false,       /* CONCURRENT_CAPTURE */
         false,       /* COMPRESS_IN */
         false,       /* BATTERY_LISTENER */
+        false,       /* MAXX_AUDIO */
         true,        /* COMPRESS_METADATA_NEEDED */
         false,       /* INCALL_MUSIC */
         false,       /* COMPRESS_VOIP */
@@ -149,6 +150,7 @@
             true,        /* CONCURRENT_CAPTURE */
             true,        /* COMPRESS_IN */
             true,        /* BATTERY_LISTENER */
+            false,       /* MAXX_AUDIO */
             true,        /* COMPRESS_METADATA_NEEDED */
             true,        /* INCALL_MUSIC */
             false,       /* COMPRESS_VOIP */
@@ -192,6 +194,7 @@
             true,        /* CONCURRENT_CAPTURE */
             false,       /* COMPRESS_IN */
             false,       /* BATTERY_LISTENER */
+            true,        /* MAXX_AUDIO */
             false,       /* COMPRESS_METADATA_NEEDED */
             true,        /* INCALL_MUSIC */
             false,       /* COMPRESS_VOIP */
diff --git a/hal/ahal_config_helper.h b/hal/ahal_config_helper.h
index 3251961..39ed68e 100644
--- a/hal/ahal_config_helper.h
+++ b/hal/ahal_config_helper.h
@@ -71,6 +71,7 @@
     bool concurrent_capture_enabled;
     bool compress_in_enabled;
     bool battery_listener_enabled;
+    bool maxx_audio_enabled;
     bool compress_metadata_needed;
     bool incall_music_enabled;
     bool compress_voip_enabled;
diff --git a/hal/audio_extn/Android.mk b/hal/audio_extn/Android.mk
old mode 100755
new mode 100644
index 59b18a2..117ee27
--- a/hal/audio_extn/Android.mk
+++ b/hal/audio_extn/Android.mk
@@ -398,11 +398,13 @@
 include $(BUILD_SHARED_LIBRARY)
 
 #-------------------------------------------
+
 #            Build EXT_HW_PLUGIN LIB
 #-------------------------------------------
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libexthwplugin
+
 LOCAL_VENDOR_MODULE := true
 
 PRIMARY_HAL_PATH := vendor/qcom/opensource/audio-hal/primary-hal/hal
@@ -705,3 +707,61 @@
 LOCAL_HEADER_LIBRARIES += libhardware_headers
 LOCAL_HEADER_LIBRARIES += libsystem_headers
 #include $(BUILD_SHARED_LIBRARY)
+
+#-------------------------------------------
+#            Build MAXX_AUDIO
+#-------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libmaxxaudio
+LOCAL_VENDOR_MODULE := true
+
+PRIMARY_HAL_PATH := vendor/qcom/opensource/audio-hal/primary-hal/hal
+AUDIO_PLATFORM := $(TARGET_BOARD_PLATFORM)
+
+ifneq ($(filter sdm845 sdm710 msmnile kona sdm660 msm8937 $(MSMSTEPPE),$(TARGET_BOARD_PLATFORM)),)
+  # B-family platform uses msm8974 code base
+  AUDIO_PLATFORM = msm8974
+  MULTIPLE_HW_VARIANTS_ENABLED := true
+endif
+
+LOCAL_SRC_FILES:= \
+        maxxaudio.c
+
+LOCAL_CFLAGS += \
+    -Wall \
+    -Werror \
+    -Wno-unused-function \
+    -Wno-unused-variable
+
+LOCAL_SHARED_LIBRARIES := \
+    libaudioutils \
+    libcutils \
+    liblog \
+    libtinyalsa \
+    libtinycompress \
+    libaudioroute \
+    libdl \
+    libexpat
+
+LOCAL_C_INCLUDES := \
+    $(PRIMARY_HAL_PATH) \
+    $(PRIMARY_HAL_PATH)/$(AUDIO_PLATFORM) \
+    external/tinyalsa/include \
+    external/tinycompress/include \
+    external/expat/lib \
+    system/media/audio_utils/include \
+    $(call include-path-for, audio-route) \
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/techpack/audio/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DLKM)),true)
+  LOCAL_HEADER_LIBRARIES += audio_kernel_headers
+  LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/vendor/qcom/opensource/audio-kernel/include
+endif
+
+LOCAL_HEADER_LIBRARIES += libhardware_headers
+LOCAL_HEADER_LIBRARIES += libsystem_headers
+include $(BUILD_SHARED_LIBRARY)
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 400d7d0..19c839c 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -62,6 +62,7 @@
 #define MEDIA_FMT_LDAC                                     0x00013224
 #define MEDIA_FMT_MP3                                      0x00010BE9
 #define MEDIA_FMT_APTX_ADAPTIVE                            0x00013204
+#define MEDIA_FMT_APTX_AD_SPEECH                           0x00013208
 #define MEDIA_FMT_AAC_AOT_LC                               2
 #define MEDIA_FMT_AAC_AOT_SBR                              5
 #define MEDIA_FMT_AAC_AOT_PS                               29
@@ -85,6 +86,7 @@
 #define MIXER_SAMPLE_RATE_DEFAULT  "BT SampleRate"
 #define MIXER_AFE_IN_CHANNELS      "AFE Input Channels"
 #define MIXER_ABR_TX_FEEDBACK_PATH "A2DP_SLIM7_UL_HL Switch"
+#define MIXER_ABR_RX_FEEDBACK_PATH "SCO_SLIM7_DL_HL Switch"
 #define MIXER_SET_FEEDBACK_CHANNEL "BT set feedback channel"
 #define MIXER_SINK_SAMPLE_RATE     "BT_TX SampleRate"
 #define MIXER_AFE_SINK_CHANNELS    "AFE Output Channels"
@@ -125,6 +127,9 @@
 // Slimbus Tx sample rate for ABR feedback channel
 #define ABR_TX_SAMPLE_RATE             "KHZ_8"
 
+// Slimbus Tx sample rate for APTX AD SPEECH
+#define SPEECH_TX_SAMPLE_RATE             "KHZ_96"
+
 // Purpose ID for Inter Module Communication (IMC) in AFE
 #define IMC_PURPOSE_ID_BT_INFO         0x000132E2
 
@@ -134,8 +139,13 @@
 // Instance identifier for A2DP
 #define MAX_INSTANCE_ID                (UINT32_MAX / 2)
 
+// Instance identifier for SWB
+#define APTX_AD_SPEECH_INSTANCE_ID                 37
+
+#define SAMPLING_RATE_96K               96000
 #define SAMPLING_RATE_48K               48000
 #define SAMPLING_RATE_441K              44100
+#define SAMPLING_RATE_32K               32000
 #define CH_STEREO                       2
 #define CH_MONO                         1
 #define SOURCE 0
@@ -172,6 +182,7 @@
     CODEC_TYPE_LDAC = AUDIO_FORMAT_LDAC, // 0x23000000UL
     CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
     CODEC_TYPE_APTX_AD = 620756992u, // 0x25000000UL
+    CODEC_TYPE_APTX_AD_SPEECH = 637534208u, //0x26000000UL
     CODEC_TYPE_PCM = AUDIO_FORMAT_PCM_16_BIT, // 0x1u
 }codec_t;
 
@@ -237,6 +248,11 @@
 } imc_status_t;
 
 typedef enum {
+    SWAP_DISABLE,
+    SWAP_ENABLE,
+} swap_status_t;
+
+typedef enum {
     MTU_SIZE,
     PEAK_BIT_RATE,
 } frame_control_type_t;
@@ -265,6 +281,8 @@
     bool abr_started;
     /* ABR Tx path pcm handle */
     struct pcm *abr_tx_handle;
+    /* ABR Rx path pcm handle */
+    struct pcm *abr_rx_handle;
     /* ABR Inter Module Communication (IMC) instance ID */
     uint32_t imc_instance;
 };
@@ -319,6 +337,7 @@
     uint32_t dec_channels;
     bool a2dp_sink_started;
     int  a2dp_sink_total_active_session_requests;
+    bool swb_configured;
 };
 
 struct a2dp_data a2dp;
@@ -400,6 +419,18 @@
     struct imc_dec_enc_info imc_info;
 } __attribute__ ((packed));
 
+struct aptx_ad_speech_mode_cfg_t
+{
+    uint32_t mode;
+    uint32_t swapping;
+} __attribute__ ((packed));
+
+/* Structure for SWB voice dec config */
+struct aptx_ad_speech_dec_cfg_t {
+    struct abr_dec_cfg_t abr_cfg;
+    struct aptx_ad_speech_mode_cfg_t speech_mode;
+} __attribute__ ((packed));
+
 /* START of DSP configurable structures
  * These values should match with DSP interface defintion
  */
@@ -546,6 +577,15 @@
     struct abr_enc_cfg_t abr_cfg;
 } __attribute__ ((packed));
 
+/* APTX AD SPEECH structure */
+struct aptx_ad_speech_enc_cfg_t
+{
+    struct custom_enc_cfg_t  custom_cfg;
+    /* Information to set up IMC between decoder and encoder */
+    struct imc_dec_enc_info imc_info;
+    struct aptx_ad_speech_mode_cfg_t speech_mode;
+} __attribute__ ((packed));
+
 struct ldac_specific_enc_cfg_t
 {
     uint32_t      bit_rate;
@@ -715,7 +755,9 @@
 static int stop_abr()
 {
     struct mixer_ctl *ctl_abr_tx_path = NULL;
+    struct mixer_ctl *ctl_abr_rx_path = NULL;
     struct mixer_ctl *ctl_set_bt_feedback_channel = NULL;
+    int ret = 0;
 
     /* This function can be used if !abr_started for clean up */
     ALOGV("%s: enter", __func__);
@@ -725,6 +767,10 @@
         pcm_close(a2dp.abr_config.abr_tx_handle);
         a2dp.abr_config.abr_tx_handle = NULL;
     }
+    if (a2dp.abr_config.abr_rx_handle != NULL) {
+        pcm_close(a2dp.abr_config.abr_rx_handle);
+        a2dp.abr_config.abr_rx_handle = NULL;
+    }
     a2dp.abr_config.abr_started = false;
     a2dp.abr_config.imc_instance = 0;
 
@@ -733,11 +779,10 @@
                                         MIXER_SET_FEEDBACK_CHANNEL);
     if (!ctl_set_bt_feedback_channel) {
         ALOGE("%s: ERROR Set usecase mixer control not identifed", __func__);
-        return -ENOSYS;
-    }
-    if (mixer_ctl_set_value(ctl_set_bt_feedback_channel, 0, 0) != 0) {
+        ret = -ENOSYS;
+    } else if (mixer_ctl_set_value(ctl_set_bt_feedback_channel, 0, 0) != 0) {
         ALOGE("%s: Failed to set BT usecase", __func__);
-        return -ENOSYS;
+        ret = -ENOSYS;
     }
 
     // Reset ABR Tx feedback path
@@ -746,19 +791,31 @@
                                         MIXER_ABR_TX_FEEDBACK_PATH);
     if (!ctl_abr_tx_path) {
         ALOGE("%s: ERROR ABR Tx feedback path mixer control not identifed", __func__);
-        return -ENOSYS;
-    }
-    if (mixer_ctl_set_value(ctl_abr_tx_path, 0, 0) != 0) {
+        ret = -ENOSYS;
+    } else if (mixer_ctl_set_value(ctl_abr_tx_path, 0, 0) != 0) {
         ALOGE("%s: Failed to set ABR Tx feedback path", __func__);
-        return -ENOSYS;
+        ret = -ENOSYS;
     }
 
-   return 0;
+    // Reset ABR Rx feedback path
+    ALOGV("%s: Disable ABR Rx feedback path", __func__);
+    ctl_abr_rx_path = mixer_get_ctl_by_name(a2dp.adev->mixer,
+                                        MIXER_ABR_RX_FEEDBACK_PATH);
+    if (!ctl_abr_rx_path) {
+        ALOGE("%s: ERROR ABR Rx feedback path mixer control not identifed", __func__);
+        ret = -ENOSYS;
+    } else if (mixer_ctl_set_value(ctl_abr_rx_path, 0, 0) != 0) {
+        ALOGE("%s: Failed to set ABR Rx feedback path", __func__);
+        ret = -ENOSYS;
+    }
+
+   return ret;
 }
 
 static int start_abr()
 {
     struct mixer_ctl *ctl_abr_tx_path = NULL;
+    struct mixer_ctl *ctl_abr_rx_path = NULL;
     struct mixer_ctl *ctl_set_bt_feedback_channel = NULL;
     int abr_device_id;
     int ret = 0;
@@ -792,11 +849,11 @@
                                         MIXER_SET_FEEDBACK_CHANNEL);
     if (!ctl_set_bt_feedback_channel) {
         ALOGE("%s: ERROR Set usecase mixer control not identifed", __func__);
-        return -ENOSYS;
+        goto fail;
     }
     if (mixer_ctl_set_value(ctl_set_bt_feedback_channel, 0, 1) != 0) {
         ALOGE("%s: Failed to set BT usecase", __func__);
-        return -ENOSYS;
+        goto fail;
     }
 
     // Open hostless front end and prepare ABR Tx path
@@ -806,19 +863,60 @@
         a2dp.abr_config.abr_tx_handle = pcm_open(a2dp.adev->snd_card,
                                                  abr_device_id, PCM_IN,
                                                  &pcm_config_abr);
-        if (a2dp.abr_config.abr_tx_handle == NULL ||
-            !pcm_is_ready(a2dp.abr_config.abr_tx_handle))
+        if (a2dp.abr_config.abr_tx_handle == NULL) {
+            ALOGE("%s: Can't open abr tx device", __func__);
             goto fail;
+        }
+        if (!(pcm_is_ready(a2dp.abr_config.abr_tx_handle) &&
+              !pcm_start(a2dp.abr_config.abr_tx_handle))) {
+            ALOGE("%s: tx: %s", __func__, pcm_get_error(a2dp.abr_config.abr_tx_handle));
+            goto fail;
+        }
     }
-    ret = pcm_start(a2dp.abr_config.abr_tx_handle);
-    if (ret < 0)
-        goto fail;
+
+    // Enable Slimbus 7 Rx feedback path for HD Voice use case
+    if (a2dp.bt_encoder_format == CODEC_TYPE_APTX_AD_SPEECH) {
+        ALOGV("%s: Enable ABR Rx feedback path", __func__);
+        ctl_abr_rx_path = mixer_get_ctl_by_name(a2dp.adev->mixer,
+                                            MIXER_ABR_RX_FEEDBACK_PATH);
+        if (!ctl_abr_rx_path) {
+            ALOGE("%s: ERROR ABR Rx feedback path mixer control not identifed", __func__);
+            goto fail;
+        }
+        if (mixer_ctl_set_value(ctl_abr_rx_path, 0, 1) != 0) {
+            ALOGE("%s: Failed to set ABR Rx feedback path", __func__);
+            goto fail;
+        }
+
+        if (mixer_ctl_set_value(ctl_set_bt_feedback_channel, 0, 1) != 0) {
+            ALOGE("%s: Failed to set BT usecase", __func__);
+            goto fail;
+        }
+
+        // Open hostless front end and prepare ABR Rx path
+        abr_device_id = fp_platform_get_pcm_device_id(USECASE_AUDIO_A2DP_ABR_FEEDBACK,
+                                                   PCM_PLAYBACK);
+        if (!a2dp.abr_config.abr_rx_handle) {
+            a2dp.abr_config.abr_rx_handle = pcm_open(a2dp.adev->snd_card,
+                                                     abr_device_id, PCM_OUT,
+                                                     &pcm_config_abr);
+            if (a2dp.abr_config.abr_rx_handle == NULL) {
+                ALOGE("%s: Can't open abr rx device", __func__);
+                goto fail;
+            }
+            if (!(pcm_is_ready(a2dp.abr_config.abr_rx_handle) &&
+                  !pcm_start(a2dp.abr_config.abr_rx_handle))) {
+                ALOGE("%s: rx: %s", __func__, pcm_get_error(a2dp.abr_config.abr_rx_handle));
+                goto fail;
+            }
+        }
+    }
+
     a2dp.abr_config.abr_started = true;
 
     return ret;
 
 fail:
-    ALOGE("%s: %s", __func__, pcm_get_error(a2dp.abr_config.abr_tx_handle));
     stop_abr();
     return -ENOSYS;
 }
@@ -965,6 +1063,7 @@
     a2dp.abr_config.abr_started = false;
     a2dp.abr_config.imc_instance = 0;
     a2dp.abr_config.abr_tx_handle = NULL;
+    a2dp.abr_config.abr_rx_handle = NULL;
     a2dp.bt_state_source = A2DP_STATE_DISCONNECTED;
 
     return 0;
@@ -1079,9 +1178,12 @@
 
         if (direction == SOURCE) {
             /* Set Tx backend sample rate */
-            if (a2dp.abr_config.is_abr_enabled)
-            rate_str = ABR_TX_SAMPLE_RATE;
-
+            if (a2dp.abr_config.is_abr_enabled) {
+                if (a2dp.bt_encoder_format == CODEC_TYPE_APTX_AD_SPEECH)
+                    rate_str = SPEECH_TX_SAMPLE_RATE;
+                else
+                    rate_str = ABR_TX_SAMPLE_RATE;
+            }
             ALOGD("%s: set backend tx sample rate = %s", __func__, rate_str);
             ctl_sample_rate = mixer_get_ctl_by_name(a2dp.adev->mixer,
                                             MIXER_SOURCE_SAMPLE_RATE_TX);
@@ -1282,17 +1384,18 @@
             ALOGE("%s: Failed to reset backend sample rate = %s", __func__, rate_str);
             return -ENOSYS;
         }
-
-        ctl_sample_rate_tx = mixer_get_ctl_by_name(a2dp.adev->mixer,
-                                        MIXER_SOURCE_SAMPLE_RATE_TX);
-        if (!ctl_sample_rate_tx) {
+        if (a2dp.abr_config.is_abr_enabled) {
+            ctl_sample_rate_tx = mixer_get_ctl_by_name(a2dp.adev->mixer,
+                                            MIXER_SOURCE_SAMPLE_RATE_TX);
+            if (!ctl_sample_rate_tx) {
                 ALOGE("%s: ERROR Tx backend sample rate mixer control not identifed", __func__);
                 return -ENOSYS;
-        }
+            }
 
-        if (mixer_ctl_set_enum_by_string(ctl_sample_rate_tx, rate_str) != 0) {
-            ALOGE("%s: Failed to reset Tx backend sample rate = %s", __func__, rate_str);
-            return -ENOSYS;
+            if (mixer_ctl_set_enum_by_string(ctl_sample_rate_tx, rate_str) != 0) {
+                ALOGE("%s: Failed to reset Tx backend sample rate = %s", __func__, rate_str);
+                return -ENOSYS;
+            }
         }
     } else {
 
@@ -1707,7 +1810,7 @@
 bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL;
-    int mixer_size;
+    int mixer_size = 0;
     bool is_configured = false;
     int ret = 0;
     int sample_rate_backup;
@@ -2209,7 +2312,7 @@
         return -ENOSYS;
     }
 
-    if (a2dp.a2dp_source_suspended == true) {
+    if (a2dp.a2dp_source_suspended || a2dp.swb_configured) {
         //session will be restarted after suspend completion
         ALOGD("a2dp start requested during suspend state");
         return -ENOSYS;
@@ -2434,6 +2537,16 @@
     }
 }
 
+static void reset_codec_config()
+{
+    reset_a2dp_enc_config_params();
+    reset_a2dp_source_dec_config_params();
+    a2dp_reset_backend_cfg(SOURCE);
+    if (a2dp.abr_config.is_abr_enabled && a2dp.abr_config.abr_started)
+        stop_abr();
+    a2dp.abr_config.is_abr_enabled = false;
+}
+
 int a2dp_stop_playback()
 {
     int ret =0;
@@ -2456,14 +2569,9 @@
             ALOGE("stop stream to BT IPC lib failed");
         else
             ALOGV("stop steam to BT IPC lib successful");
-        reset_a2dp_enc_config_params();
-        reset_a2dp_source_dec_config_params();
-        a2dp_reset_backend_cfg(SOURCE);
-        if (a2dp.abr_config.is_abr_enabled && a2dp.abr_config.abr_started)
-            stop_abr();
-        a2dp.abr_config.is_abr_enabled = false;
+        if (!a2dp.a2dp_source_suspended && !a2dp.swb_configured)
+            reset_codec_config();
         a2dp.a2dp_source_started = false;
-        a2dp_reset_backend_cfg(SOURCE);
     }
     if (!a2dp.a2dp_source_total_active_session_requests)
        a2dp.a2dp_source_started = false;
@@ -2578,8 +2686,8 @@
                         pthread_mutex_lock(&a2dp.adev->lock);
                     }
                 }
-                reset_a2dp_enc_config_params();
-                reset_a2dp_source_dec_config_params();
+                if (!a2dp.swb_configured)
+                    reset_codec_config();
                 if (a2dp.audio_source_suspend)
                    a2dp.audio_source_suspend();
             } else if (a2dp.a2dp_source_suspended == true) {
@@ -2699,8 +2807,11 @@
   a2dp.abr_config.abr_started = false;
   a2dp.abr_config.imc_instance = 0;
   a2dp.abr_config.abr_tx_handle = NULL;
+  a2dp.abr_config.abr_rx_handle = NULL;
   a2dp.is_tws_mono_mode_on = false;
   a2dp_source_init();
+  a2dp.swb_configured = false;
+
   // init function pointers
   fp_platform_get_pcm_device_id =
               init_config.fp_platform_get_pcm_device_id;
@@ -2802,3 +2913,112 @@
 
     return 0;
 }
+
+
+bool configure_aptx_ad_speech_enc_fmt() {
+    struct mixer_ctl *ctl_enc_data = NULL;
+    int mixer_size = 0;
+    int ret = 0;
+    struct aptx_ad_speech_enc_cfg_t aptx_dsp_cfg;
+
+    ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
+    if (!ctl_enc_data) {
+        ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
+        return false;
+    }
+
+    /* Initialize dsp configuration params */
+    memset(&aptx_dsp_cfg, 0x0, sizeof(struct aptx_ad_speech_enc_cfg_t));
+    aptx_dsp_cfg.custom_cfg.enc_format = MEDIA_FMT_APTX_AD_SPEECH;
+    aptx_dsp_cfg.custom_cfg.sample_rate = SAMPLING_RATE_32K;
+    aptx_dsp_cfg.custom_cfg.num_channels = CH_MONO;
+    aptx_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+    aptx_dsp_cfg.imc_info.direction = IMC_RECEIVE;
+    aptx_dsp_cfg.imc_info.enable = IMC_ENABLE;
+    aptx_dsp_cfg.imc_info.purpose = IMC_PURPOSE_ID_BT_INFO;
+    aptx_dsp_cfg.imc_info.comm_instance = APTX_AD_SPEECH_INSTANCE_ID;
+    aptx_dsp_cfg.speech_mode.mode = a2dp.adev->swb_speech_mode;
+    aptx_dsp_cfg.speech_mode.swapping = SWAP_ENABLE;
+
+    /* Configure AFE DSP configuration */
+    mixer_size = sizeof(struct aptx_ad_speech_enc_cfg_t);
+    ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
+                  mixer_size);
+    if (ret != 0) {
+        ALOGE("%s: Failed to set SWB encoder config", __func__);
+        return false;
+    }
+
+    /* Configure AFE Input Bit Format as PCM_16 */
+    ret = a2dp_set_bit_format(DEFAULT_ENCODER_BIT_FORMAT);
+    if (ret != 0) {
+        ALOGE("%s: Failed to set SWB bit format", __func__);
+        return false;
+    }
+
+    return true;
+}
+
+bool configure_aptx_ad_speech_dec_fmt()
+{
+    struct mixer_ctl *ctl_dec_data = NULL;
+    struct aptx_ad_speech_dec_cfg_t dec_cfg;
+    int ret = 0;
+
+    ctl_dec_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_SOURCE_DEC_CONFIG_BLOCK);
+    if (!ctl_dec_data) {
+        ALOGE("%s: ERROR codec config data mixer control not identifed", __func__);
+        return false;
+    }
+    memset(&dec_cfg, 0x0, sizeof(dec_cfg));
+    dec_cfg.abr_cfg.dec_format = MEDIA_FMT_APTX_AD_SPEECH;
+    dec_cfg.abr_cfg.imc_info.direction = IMC_TRANSMIT;
+    dec_cfg.abr_cfg.imc_info.enable = IMC_ENABLE;
+    dec_cfg.abr_cfg.imc_info.purpose = IMC_PURPOSE_ID_BT_INFO;
+    dec_cfg.abr_cfg.imc_info.comm_instance = APTX_AD_SPEECH_INSTANCE_ID;
+    dec_cfg.speech_mode.mode = a2dp.adev->swb_speech_mode;
+    dec_cfg.speech_mode.swapping = SWAP_ENABLE;
+
+    ret = mixer_ctl_set_array(ctl_dec_data, &dec_cfg,
+                              sizeof(dec_cfg));
+    if (ret != 0) {
+        ALOGE("%s: Failed to set decoder config", __func__);
+        return false;
+    }
+      return true;
+}
+
+int sco_start_configuration()
+{
+    ALOGD("sco_start_configuration start");
+
+    if (!a2dp.swb_configured) {
+        a2dp.bt_encoder_format = CODEC_TYPE_APTX_AD_SPEECH;
+        /* Configure AFE codec*/
+        if (configure_aptx_ad_speech_enc_fmt() &&
+            configure_aptx_ad_speech_dec_fmt()) {
+            ALOGD("%s: SCO enc/dec configured successfully", __func__);
+        } else {
+            ALOGE("%s: failed to send SCO configuration", __func__);
+            return -ETIMEDOUT;
+        }
+        /* Configure backend*/
+        a2dp.enc_sampling_rate = SAMPLING_RATE_96K;
+        a2dp.enc_channels = CH_MONO;
+        a2dp.abr_config.is_abr_enabled = true;
+        a2dp_set_backend_cfg(SOURCE);
+        /* Start abr*/
+        start_abr();
+        a2dp.swb_configured = true;
+    }
+    return 0;
+}
+
+void sco_reset_configuration()
+{
+    ALOGD("sco_reset_configuration start");
+
+    reset_codec_config();
+    a2dp.bt_encoder_format = CODEC_TYPE_INVALID;
+    a2dp.swb_configured = false;
+}
diff --git a/hal/audio_extn/adsp_hdlr.c b/hal/audio_extn/adsp_hdlr.c
index 31a6b16..f8c8133 100644
--- a/hal/audio_extn/adsp_hdlr.c
+++ b/hal/audio_extn/adsp_hdlr.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, 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
@@ -457,7 +457,7 @@
 
 int audio_extn_adsp_hdlr_stream_register_event(void *handle, void *data,
                                                adsp_event_callback_t cb,
-                                               void *cookie)
+                                               void *cookie, bool is_adm_event)
 {
     int ret = 0;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
@@ -480,14 +480,22 @@
         ALOGE("%s: Invalid payload_length %d",__func__, param->payload_length);
         return -EINVAL;
     }
-    ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
+
+    if (is_adm_event)
+        ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
+            "ADSP COPP Callback Event");
+    else
+        ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
             "ADSP Stream Callback Event %d", config->pcm_device_id);
+
     if (ret < 0) {
         ALOGE("%s: snprintf failed",__func__);
         ret = -EINVAL;
         goto done;
     }
+
     ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, cb_mixer_ctl_name);
+
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
               cb_mixer_ctl_name);
@@ -495,8 +503,13 @@
         goto done;
     }
 
-    ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+    if (is_adm_event)
+        ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+            "COPP Event Cmd");
+    else
+       ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "ADSP Stream Cmd %d", config->pcm_device_id);
+
     if (ret < 0) {
         ALOGE("%s: snprintf failed",__func__);
         ret = -EINVAL;
@@ -504,12 +517,14 @@
     }
 
     ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, mixer_ctl_name);
+
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
               mixer_ctl_name);
         ret = -EINVAL;
         goto done;
     }
+
     ALOGD("%s: event = %d, payload_length %d", __func__, param->event_type, param->payload_length);
 
     /* copy event_type, payload size and payload */
@@ -521,6 +536,7 @@
            param->payload, param->payload_length);
     ret = mixer_ctl_set_array(ctl, payload, (sizeof(param->event_type) +
                                sizeof(param->payload_length) + param->payload_length));
+
     if (ret < 0) {
         ALOGE("%s: Could not set ctl for mixer cmd - %s, ret %d", __func__,
               mixer_ctl_name, ret);
@@ -537,23 +553,27 @@
 
         /* create event threads during first event registration */
         pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
+
         if (!adsp_hdlr_inst->event_wait_thread_active)
             create_event_wait_thread(adsp_hdlr_inst);
-        pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
 
+        pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
         pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
+
         if (!adsp_hdlr_inst->event_callback_thread_active)
             create_event_callback_thread(adsp_hdlr_inst);
-        pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
 
+        pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
         send_cmd_event_wait_thread(adsp_hdlr_inst, EVENT_CMD_WAIT);
     }
+
     event_info = (struct adsp_hdlr_event_info *) calloc(1,
                                    sizeof(struct adsp_hdlr_event_info));
     if (event_info == NULL) {
         ret = -ENOMEM;
         goto done;
     }
+
     event_info->event_type = param->event_type;
     event_info->cb = cb;
     event_info->cookie = cookie;
@@ -582,7 +602,7 @@
 
     switch (cmd) {
         case ADSP_HDLR_STREAM_CMD_REGISTER_EVENT :
-            ret = audio_extn_adsp_hdlr_stream_register_event(handle, param, NULL, NULL);
+            ret = audio_extn_adsp_hdlr_stream_register_event(handle, param, NULL, NULL, false);
             if (ret)
                 ALOGE("%s:adsp_hdlr_stream_register_event failed error %d",
                        __func__, ret);
diff --git a/hal/audio_extn/adsp_hdlr.h b/hal/audio_extn/adsp_hdlr.h
index 1c257fc..4ba9cb3 100644
--- a/hal/audio_extn/adsp_hdlr.h
+++ b/hal/audio_extn/adsp_hdlr.h
@@ -57,7 +57,7 @@
                     adsp_hdlr_cmd_t cmd,
                     void *param);
 int audio_extn_adsp_hdlr_stream_register_event(void *handle,
-                void *param, adsp_event_callback_t cb, void *cookie);
+                void *param, adsp_event_callback_t cb, void *cookie, bool is_adm_event);
 int audio_extn_adsp_hdlr_stream_deregister_event(void *handle, void *param);
 #else
 #define audio_extn_adsp_hdlr_init(mixer)                                     (0)
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index a0b1949..3fd4b85 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2017-2019, 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
@@ -217,6 +217,7 @@
 typedef enum {
     AUDIO_STREAM_PP_EVENT = 0,
     AUDIO_STREAM_ENCDEC_EVENT = 1,
+    AUDIO_COPP_EVENT = 3,
 } audio_event_id;
 
 /* payload format for HAL parameter
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 431c248..24ed4c5 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -189,6 +189,7 @@
 static bool audio_extn_concurrent_capture_enabled = false;
 static bool audio_extn_compress_in_enabled = false;
 static bool audio_extn_battery_listener_enabled = false;
+static bool audio_extn_maxx_audio_enabled = false;
 
 #define AUDIO_PARAMETER_KEY_AANC_NOISE_LEVEL "aanc_noise_level"
 #define AUDIO_PARAMETER_KEY_ANC        "anc_enabled"
@@ -3791,6 +3792,13 @@
 typedef int (*a2dp_stop_capture_t)();
 static a2dp_stop_capture_t a2dp_stop_capture;
 
+typedef int (*sco_start_configuration_t)();
+static sco_start_configuration_t sco_start_configuration;
+
+typedef void (*sco_reset_configuration_t)();
+static sco_reset_configuration_t sco_reset_configuration;
+
+
 int a2dp_offload_feature_init(bool is_feature_enabled)
 {
     ALOGD("%s: Called with feature %s", __func__,
@@ -3842,6 +3850,15 @@
             ALOGE("%s: dlsym failed", __func__);
             goto feature_disabled;
         }
+        // initialize APIs for SWB extension
+        if (!(sco_start_configuration =
+                 (sco_start_configuration_t)dlsym(a2dp_lib_handle, "sco_start_configuration")) ||
+             !(sco_reset_configuration =
+                 (sco_reset_configuration_t)dlsym(a2dp_lib_handle, "sco_reset_configuration"))) {
+            ALOGE("%s: dlsym failed for swb APIs", __func__);
+            sco_start_configuration = NULL;
+            sco_reset_configuration = NULL;
+        }
         ALOGD("%s:: ---- Feature A2DP_OFFLOAD is Enabled ----", __func__);
         return 0;
     }
@@ -3965,6 +3982,16 @@
     return (a2dp_stop_capture ? a2dp_stop_capture() : 0);
 }
 
+int audio_extn_sco_start_configuration()
+{
+    return (sco_start_configuration? sco_start_configuration() : 0);
+}
+
+void audio_extn_sco_reset_configuration()
+{
+    return (sco_reset_configuration? sco_reset_configuration() : 0);
+}
+
 // END: A2DP_OFFLOAD =====================================================================
 
 // START: HFP ======================================================================
@@ -4722,6 +4749,134 @@
 {
     return (batt_prop_is_charging)? batt_prop_is_charging(): false;
 }
+// END: BATTERY_LISTENER ================================================================
+
+// START: MAXX_AUDIO =====================================================================
+#ifdef __LP64__
+#define MAXX_AUDIO_LIB_PATH "/vendor/lib64/libmaxxaudio.so"
+#else
+#define MAXX_AUDIO_LIB_PATH "/vendor/lib/libmaxxaudio.so"
+#endif
+
+static void *maxxaudio_lib_handle = NULL;
+
+typedef void (*maxxaudio_init_t)(void *, maxx_audio_init_config_t);
+static maxxaudio_init_t maxxaudio_init;
+
+typedef void (*maxxaudio_deinit_t)();
+static maxxaudio_deinit_t maxxaudio_deinit;
+
+typedef bool (*maxxaudio_set_state_t)(struct audio_device*, int,
+                             float, bool);
+static maxxaudio_set_state_t maxxaudio_set_state;
+
+typedef void (*maxxaudio_set_device_t)(struct audio_usecase *);
+static maxxaudio_set_device_t maxxaudio_set_device;
+
+typedef void (*maxxaudio_set_parameters_t)(struct audio_device *,
+                                  struct str_parms *);
+static maxxaudio_set_parameters_t maxxaudio_set_parameters;
+
+typedef bool (*maxxaudio_supported_usb_t)();
+static maxxaudio_supported_usb_t maxxaudio_supported_usb;
+
+int maxx_audio_feature_init(bool is_feature_enabled)
+{
+    audio_extn_maxx_audio_enabled = is_feature_enabled;
+    ALOGD("%s: Called with feature %s", __func__,
+                  is_feature_enabled ? "Enabled" : "NOT Enabled");
+    if (is_feature_enabled) {
+        // dlopen lib
+        maxxaudio_lib_handle = dlopen(MAXX_AUDIO_LIB_PATH, RTLD_NOW);
+
+        if (!maxxaudio_lib_handle) {
+            ALOGE("%s: dlopen failed", __func__);
+            goto feature_disabled;
+        }
+
+        if (!(maxxaudio_init =
+                    (maxxaudio_init_t)dlsym(maxxaudio_lib_handle, "ma_init")) ||
+            !(maxxaudio_deinit =
+                 (maxxaudio_deinit_t)dlsym(maxxaudio_lib_handle, "ma_deinit")) ||
+            !(maxxaudio_set_state =
+                 (maxxaudio_set_state_t)dlsym(maxxaudio_lib_handle, "ma_set_state")) ||
+            !(maxxaudio_set_device =
+                 (maxxaudio_set_device_t)dlsym(maxxaudio_lib_handle, "ma_set_device")) ||
+            !(maxxaudio_set_parameters =
+                 (maxxaudio_set_parameters_t)dlsym(maxxaudio_lib_handle, "ma_set_parameters")) ||
+            !(maxxaudio_supported_usb =
+                 (maxxaudio_supported_usb_t)dlsym(
+                                    maxxaudio_lib_handle, "ma_supported_usb"))) {
+            ALOGE("%s: dlsym failed", __func__);
+            goto feature_disabled;
+        }
+        ALOGD("%s:: ---- Feature MAXX_AUDIO is Enabled ----", __func__);
+        return 0;
+    }
+
+feature_disabled:
+    if (maxxaudio_lib_handle) {
+        dlclose(maxxaudio_lib_handle);
+        maxxaudio_lib_handle = NULL;
+    }
+
+    maxxaudio_init = NULL;
+    maxxaudio_deinit = NULL;
+    maxxaudio_set_state = NULL;
+    maxxaudio_set_device = NULL;
+    maxxaudio_set_parameters = NULL;
+    maxxaudio_supported_usb = NULL;
+    ALOGW(":: %s: ---- Feature MAXX_AUDIO is disabled ----", __func__);
+    return -ENOSYS;
+}
+
+bool audio_extn_is_maxx_audio_enabled()
+{
+    return audio_extn_maxx_audio_enabled;
+}
+
+void audio_extn_ma_init(void *platform)
+{
+
+     if (maxxaudio_init) {
+        maxx_audio_init_config_t init_config;
+        init_config.fp_platform_set_parameters = platform_set_parameters;
+        init_config.fp_audio_extn_get_snd_card_split = audio_extn_get_snd_card_split;
+        maxxaudio_init(platform, init_config);
+     }
+}
+
+void audio_extn_ma_deinit()
+{
+     if (maxxaudio_deinit)
+        maxxaudio_deinit();
+}
+
+bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
+                             float vol, bool active)
+{
+    return (maxxaudio_set_state ?
+                maxxaudio_set_state(adev, stream_type, vol, active): false);
+}
+
+void audio_extn_ma_set_device(struct audio_usecase *usecase)
+{
+    if (maxxaudio_set_device)
+        maxxaudio_set_device(usecase);
+}
+
+void audio_extn_ma_set_parameters(struct audio_device *adev,
+                                  struct str_parms *parms)
+{
+    if (maxxaudio_set_parameters)
+        maxxaudio_set_parameters(adev, parms);
+}
+
+bool audio_extn_ma_supported_usb()
+{
+    return (maxxaudio_supported_usb ? maxxaudio_supported_usb(): false);
+}
+// END: MAXX_AUDIO =====================================================================
 
 void audio_extn_feature_init(int is_running_with_enhanced_fwk)
 {
@@ -4831,6 +4986,9 @@
             case BATTERY_LISTENER:
                 battery_listener_feature_init(enable);
                 break;
+            case MAXX_AUDIO:
+                maxx_audio_feature_init(enable);
+                break;
             default:
                 break;
         }
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 51e3ba2..e1e3ca0 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -313,6 +313,9 @@
 bool audio_extn_a2dp_source_is_suspended();
 int audio_extn_a2dp_start_capture();
 int audio_extn_a2dp_stop_capture();
+int audio_extn_sco_start_configuration();
+void audio_extn_sco_reset_configuration();
+
 
 // --- Function pointers from audio_extn needed by A2DP_OFFLOAD
 typedef int (*fp_check_a2dp_restore_t)(struct audio_device *,
@@ -323,7 +326,24 @@
 };
 typedef struct a2dp_offload_init_config a2dp_offload_init_config_t;
 // END: A2DP_OFFLOAD FEATURE ====================================================
-
+// START: MAXX_AUDIO FEATURE ==================================================
+void audio_extn_ma_init(void *platform);
+void audio_extn_ma_deinit();
+bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
+                             float vol, bool active);
+void audio_extn_ma_set_device(struct audio_usecase *usecase);
+void audio_extn_ma_set_parameters(struct audio_device *adev,
+                                  struct str_parms *parms);
+bool audio_extn_ma_supported_usb();
+bool audio_extn_is_maxx_audio_enabled();
+typedef int (*fp_platform_set_parameters_t)(void*, struct str_parms*);
+// --- Function pointers from audio_extn needed by MAXX_AUDIO
+struct maxx_audio_init_config {
+    fp_platform_set_parameters_t fp_platform_set_parameters;
+    fp_audio_extn_get_snd_card_split_t fp_audio_extn_get_snd_card_split;
+};
+typedef struct maxx_audio_init_config maxx_audio_init_config_t;
+// START: MAXX_AUDIO FEATURE ==================================================
 //START: SSRRC_FEATURE ==========================================================
 bool audio_extn_ssr_check_usecase(struct stream_in *in);
 int audio_extn_ssr_set_usecase(struct stream_in *in,
diff --git a/hal/audio_extn/audio_feature_manager.c b/hal/audio_extn/audio_feature_manager.c
index a3120df..e121426 100644
--- a/hal/audio_extn/audio_feature_manager.c
+++ b/hal/audio_extn/audio_feature_manager.c
@@ -168,6 +168,8 @@
             return confValues->compress_in_enabled;
         case BATTERY_LISTENER:
             return confValues->battery_listener_enabled;
+        case MAXX_AUDIO:
+            return confValues->maxx_audio_enabled;
         case COMPRESS_METADATA_NEEDED:
             return confValues->compress_metadata_needed;
         case INCALL_MUSIC:
diff --git a/hal/audio_extn/audio_feature_manager.h b/hal/audio_extn/audio_feature_manager.h
index 9e3c541..8df076c 100644
--- a/hal/audio_extn/audio_feature_manager.h
+++ b/hal/audio_extn/audio_feature_manager.h
@@ -70,6 +70,7 @@
     COMPRESS_IN_CAPTURE,
     BATTERY_LISTENER,
     COMPRESS_METADATA_NEEDED,
+    MAXX_AUDIO,
     COMPRESS_VOIP,
     VOICE_START = COMPRESS_VOIP,
     DYNAMIC_ECNS,
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 5366066..76c8873 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, 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
@@ -553,7 +553,8 @@
         inout->adsp_hdlr_stream_handle = NULL;
         goto exit;
     }
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format,false, true)) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format,false, true) ||
+        audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform)) {
         ret = audio_extn_ip_hdlr_intf_init(&inout->ip_hdlr_handle, NULL, NULL, adev,
                                            USECASE_AUDIO_TRANSCODE_LOOPBACK_RX);
         if (ret < 0) {
diff --git a/hal/audio_extn/ip_hdlr_intf.c b/hal/audio_extn/ip_hdlr_intf.c
old mode 100755
new mode 100644
index 3d5e1fe..0afc705
--- a/hal/audio_extn/ip_hdlr_intf.c
+++ b/hal/audio_extn/ip_hdlr_intf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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
@@ -56,12 +56,19 @@
 #include "audio_extn.h"
 #include "platform_api.h"
 #include "adsp_hdlr.h"
+#include "audio_hw.h"
 
 /* These values defined by ADSP */
 #define ADSP_DEC_SERVICE_ID 1
 #define ADSP_EVENT_ID_RTIC            0x00013239
 #define ADSP_EVENT_ID_RTIC_FAIL       0x0001323A
+#define TRUMPET_TOPOLOGY 0x11000099
+#define TRUMPET_MODULE 0x0001099A
 
+struct lib_fd_info {
+    int32_t fd;
+    int32_t flag;
+};
 struct ip_hdlr_stream {
     struct listnode list;
     void *stream;
@@ -74,35 +81,109 @@
     int (*deinit)(void *handle);
     int (*open)(void *handle, bool is_dsp_decode, void *aud_sess_handle);
     int (*shm_info)(void *handle, int *fd);
+    int (*shm_pp_info)(void *handle, int *fd);
+    int (*shm_pp)(void *handle, bool is_adm_event);
     int (*get_lib_fd)(void *handle, int *lib_fd);
     int (*close)(void *handle);
     int (*event)(void *handle, void *payload);
     int (*reg_cb)(void *handle, void *ack_cb, void *fail_cb);
+    int (*event_adm)(void *handle, void *payload);
+    int (*deinit_lib)(void *handle);
+
 
     struct listnode stream_list;
     pthread_mutex_t stream_list_lock;
     int ref_cnt;
+    bool lib_fd_created;
+    void *ip_lib_handle; /*handle for dlclose of adsp lib*/
+    bool adm_event;
+    bool asm_event;
+    void *ip_dev_handle;
 };
 static struct ip_hdlr_intf *ip_hdlr = NULL;
-
+static bool adm_event_enable;
+static bool asm_event_enable;
+struct copp_cal_info {
+    uint32_t             persist;
+    uint32_t             snd_dev_id;
+    audio_devices_t      dev_id;
+    int32_t              acdb_dev_id;
+    uint32_t             app_type;
+    uint32_t             topo_id;
+    uint32_t             sampling_rate;
+    uint32_t             cal_type;
+    uint32_t             module_id;
+#ifdef INSTANCE_ID_ENABLED
+    uint16_t             instance_id;
+    uint16_t             reserved;
+#endif
+    uint32_t             param_id;
+};
+static struct copp_cal_info trumpet_data;
 /* RTIC ack information */
 struct rtic_ack_info {
     uint32_t token;
     uint32_t status;
 };
 
+struct module_info {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t token_coppidx;
+};
+
+struct rtic_ack_info_adm {
+    uint32_t token;
+    uint32_t status;
+    struct module_info mod_data;
+};
+
 /* RTIC ack format sent to ADSP */
 struct rtic_ack_param {
     uint32_t param_size;
     struct rtic_ack_info rtic_ack;
 };
 
+struct rtic_ack_param_adm {
+    uint32_t param_size;
+    struct rtic_ack_info rtic_ack;
+    struct module_info mod_data;
+};
+
 /* each event payload format */
 struct reg_ev_pl {
     uint32_t event_id;
     uint32_t cfg_mask;
 };
 
+struct reg_ev_pl_adm {
+    uint32_t event_id;
+    uint32_t module_id;
+    uint16_t instance_id;
+    uint16_t reserved;
+    uint32_t cfg_mask;
+};
+
+struct adm_pp_module {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t be_id;
+    uint32_t fe_id;
+};
+
+struct adm_fd_info {
+    uint32_t fd;
+    struct adm_pp_module adm_pp_pl_fd;
+};
+/* adm event registration format */
+struct adm_reg_event {
+    struct adm_pp_module adm_info;
+    uint16_t version;
+    uint32_t num_reg_events;
+    struct reg_ev_pl_adm rtic;
+    struct reg_ev_pl_adm rtic_fail;
+};
+
 /* event registration format */
 struct reg_event {
     uint16_t version;
@@ -121,23 +202,50 @@
     uint8_t payload[0];
 };
 
+int audio_extn_ip_hdlr_copp_update_cal_info(void *cfg, void *data)
+{
+    int ret = 0;
+    acdb_audio_cal_cfg_t *cal = (acdb_audio_cal_cfg_t*) cfg;
+    adm_event_enable = true; /* default enable with trumpet cal */
+
+    memcpy(&trumpet_data, cal, sizeof(struct copp_cal_info));
+    return ret;
+
+}
+bool audio_extn_ip_hdlr_intf_supported_for_copp(void *platform)
+{
+    return adm_event_enable;
+}
 bool audio_extn_ip_hdlr_intf_supported(audio_format_t format,
                     bool is_direct_passthrough,
                     bool is_transcode_loopback)
 {
 
-    if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_DOLBY_TRUEHD)
+    if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_DOLBY_TRUEHD) {
+        asm_event_enable = true;
         return true;
-    else if (!is_direct_passthrough && !audio_extn_qaf_is_enabled() &&
+    } else if (!is_direct_passthrough && !audio_extn_qaf_is_enabled() &&
             (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3) ||
-             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3)))
+             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3))) {
+        asm_event_enable = true;
         return true;
-    else if (is_transcode_loopback &&
+    } else if (is_transcode_loopback &&
             (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3) ||
-             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3)))
+             ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3))) {
+        asm_event_enable = true;
         return true;
-    else
+    } else {
+        asm_event_enable = false;
         return false;
+    }
+}
+
+int audio_extn_ip_hdlr_intf_event_adm(void *stream_handle __unused,
+                               void *payload, void *ip_hdlr_handle )
+{
+    ALOGVV("%s:[%d] handle = %p\n",__func__, ip_hdlr->ref_cnt, ip_hdlr_handle);
+
+    return ip_hdlr->event_adm(ip_hdlr_handle, payload);
 }
 
 int audio_extn_ip_hdlr_intf_event(void *stream_handle __unused, void *payload, void *ip_hdlr_handle )
@@ -147,7 +255,82 @@
     return ip_hdlr->event(ip_hdlr_handle, payload);
 }
 
-int audio_extn_ip_hdlr_intf_rtic_ack(void *aud_sess_handle, struct rtic_ack_info *info)
+int audio_extn_ip_hdlr_intf_rtic_ack_adm(void *aud_sess_handle,
+                               struct rtic_ack_info_adm *info)
+{
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    int ret = 0;
+    int pcm_device_id = 0;
+    struct mixer_ctl *ctl = NULL;
+    struct rtic_ack_param_adm param;
+    struct listnode *node = NULL, *tempnode = NULL;
+    struct ip_hdlr_stream *stream_info = NULL;
+    struct audio_device *adev = NULL;
+    audio_usecase_t usecase = 0;
+
+    memset(&param, 0, sizeof(struct rtic_ack_param_adm));
+    pthread_mutex_lock(&ip_hdlr->stream_list_lock);
+    list_for_each_safe(node, tempnode, &ip_hdlr->stream_list) {
+        stream_info = node_to_item(node, struct ip_hdlr_stream, list);
+        /* send the error if rtic failure notifcation is received */
+        if ((stream_info->stream == aud_sess_handle) &&
+            (stream_info->usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)) {
+            struct stream_inout *inout = (struct stream_inout *)aud_sess_handle;
+            usecase = stream_info->usecase;
+            adev = inout->dev;
+            break;
+        } else if (stream_info->stream == aud_sess_handle) {
+            struct stream_out *out = (struct stream_out *)aud_sess_handle;
+            usecase = stream_info->usecase;
+            adev = out->dev;
+            break;
+        }
+    }
+    pthread_mutex_unlock(&ip_hdlr->stream_list_lock);
+
+    if (adev == NULL) {
+        ALOGE("%s:[%d] Invalid adev", __func__, ip_hdlr->ref_cnt);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    pcm_device_id = platform_get_pcm_device_id(usecase, PCM_PLAYBACK);
+
+    ALOGVV("%s:[%d] token = %d, info->status = %d, pcm_id = %d\n",__func__,
+          ip_hdlr->ref_cnt, info->token, info->status, pcm_device_id);
+
+    /* set mixer control to send RTIC done information */
+    ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                   "COPP Event Ack");
+    if (ret < 0) {
+        ALOGE("%s:[%d] snprintf failed",__func__, ip_hdlr->ref_cnt);
+        ret = -EINVAL;
+        goto done;
+    }
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s:[%d] Could not get ctl for mixer cmd - %s", __func__,
+              ip_hdlr->ref_cnt, mixer_ctl_name);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    param.param_size = sizeof(struct rtic_ack_info);
+    memcpy(&param.rtic_ack, info, sizeof(struct rtic_ack_info));
+    memcpy(&param.mod_data, &info->mod_data, sizeof(struct module_info));
+    ret = mixer_ctl_set_array(ctl, (void *)&param, sizeof(param));
+    if (ret < 0) {
+        ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d",
+                    __func__, ip_hdlr->ref_cnt, mixer_ctl_name, ret);
+        goto done;
+    }
+
+done:
+    return ret;
+}
+
+int audio_extn_ip_hdlr_intf_rtic_ack(void *aud_sess_handle,
+                                struct rtic_ack_info *info)
 {
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
     int ret = 0;
@@ -257,6 +440,139 @@
     return 0;
 }
 
+static int audio_extn_ip_hdlr_intf_open_adm_event(void *handle,
+                    void *stream_handle, audio_usecase_t usecase)
+{
+    int ret = 0, fd = 0, pcm_device_id = 0;
+    struct adm_fd_info *fd_param_data = NULL;
+    struct audio_adsp_event *param = NULL;
+    struct adm_reg_event *reg_ev = NULL;
+    size_t shm_size = 0;
+    void  *shm_buf = NULL;
+    struct stream_out *out = NULL;
+    struct stream_inout *inout = NULL;
+    void *adsp_hdlr_stream_handle = NULL;
+    struct audio_device *dev = NULL;
+    struct mixer_ctl *ctl = NULL;
+    struct audio_usecase *uc = NULL;
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+
+    param = (struct audio_adsp_event *)calloc(1,
+                sizeof(struct audio_adsp_event));
+
+    if (param == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    reg_ev = (struct adm_reg_event *)calloc(1, sizeof(struct adm_reg_event));
+
+    if (reg_ev == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    fd_param_data = (struct adm_fd_info *)calloc(1, sizeof(struct adm_fd_info));
+
+    if (fd_param_data == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    uc = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+    if (uc == NULL) {
+        ret = -ENOMEM;
+        goto done;
+    }
+
+    if (usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX) {
+        inout = (struct stream_inout *)stream_handle;
+        adsp_hdlr_stream_handle = inout->adsp_hdlr_stream_handle;
+        dev = inout->dev;
+    } else {
+        out = (struct stream_out *)stream_handle;
+        adsp_hdlr_stream_handle = out->adsp_hdlr_stream_handle;
+        dev = out->dev;
+    }
+    uc = get_usecase_from_list(dev, usecase);
+
+    reg_ev->adm_info.module_id = TRUMPET_MODULE;
+    reg_ev->adm_info.instance_id = 0;
+    reg_ev->adm_info.be_id = platform_get_snd_device_backend_index(
+                                                uc->out_snd_device);
+    reg_ev->adm_info.fe_id = platform_get_pcm_device_id(usecase, PCM_PLAYBACK);
+    reg_ev->num_reg_events = 2;
+    reg_ev->rtic.event_id = ADSP_EVENT_ID_RTIC;
+    reg_ev->rtic.module_id = TRUMPET_MODULE;
+    reg_ev->rtic.instance_id = 0;
+    reg_ev->rtic.cfg_mask = 1; /* event enabled */
+    reg_ev->rtic_fail.event_id = ADSP_EVENT_ID_RTIC_FAIL;
+    reg_ev->rtic_fail.module_id = TRUMPET_MODULE;
+    reg_ev->rtic_fail.instance_id = 0;
+    reg_ev->rtic_fail.cfg_mask = 1; /* event enabled */
+
+    param->event_type = AUDIO_COPP_EVENT;
+    param->payload_length = sizeof(struct adm_reg_event);
+    param->payload = reg_ev;
+    bool is_adm_event = true;
+
+    /* Register for event and its callback */
+    ret = audio_extn_adsp_hdlr_stream_register_event(adsp_hdlr_stream_handle,
+               param, audio_extn_ip_hdlr_intf_event_adm, handle, is_adm_event);
+    if (ret < 0) {
+        ALOGE("%s:[%d] failed to register event",__func__,
+                                    ip_hdlr->ref_cnt, ret);
+        goto done;
+    }
+
+    ip_hdlr->reg_cb(handle, &audio_extn_ip_hdlr_intf_rtic_ack_adm,
+                                &audio_extn_ip_hdlr_intf_rtic_fail);
+    ip_hdlr->shm_pp_info(handle, &fd);
+    fd_param_data->fd = fd;
+    memcpy(&fd_param_data->adm_pp_pl_fd, &reg_ev->adm_info,
+                                sizeof(struct adm_pp_module));
+
+    ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "COPP ION FD");
+
+    if (ret < 0) {
+        ALOGE("%s:[%d] snprintf failed",__func__, ip_hdlr->ref_cnt, ret);
+        goto done;
+    }
+    ALOGV("%s: fd = %d\n", __func__, fd);
+
+    ctl = mixer_get_ctl_by_name(dev->mixer, mixer_ctl_name);
+
+    if (!ctl) {
+        ALOGE("%s:[%d] Could not get ctl for mixer cmd - %s", __func__,
+              ip_hdlr->ref_cnt, mixer_ctl_name);
+        ret = -EINVAL;
+        goto done;
+    }
+    ret = mixer_ctl_set_array(ctl, fd_param_data, sizeof(fd_param_data));
+
+    if (ret < 0) {
+        ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d"
+                , __func__, ip_hdlr->ref_cnt, mixer_ctl_name, ret);
+        goto done;
+    }
+
+done:
+    if (param)
+        free(param);
+
+    if (reg_ev)
+        free(reg_ev);
+
+    if (fd_param_data)
+        free(fd_param_data);
+
+    if (uc)
+        free(uc);
+
+    return ret;
+}
+
 static int audio_extn_ip_hdlr_intf_open_dsp(void *handle, void *stream_handle, audio_usecase_t usecase)
 {
     int ret = 0, fd = 0, pcm_device_id = 0;
@@ -268,7 +584,7 @@
     struct audio_device *dev = NULL;
     struct mixer_ctl *ctl = NULL;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
-
+    bool is_adm_event = false;
     param = (struct audio_adsp_event *)calloc(1, sizeof(struct audio_adsp_event));
     if (!param)
         return -ENOMEM;
@@ -301,7 +617,7 @@
     /* Register for event and its callback */
     ret = audio_extn_adsp_hdlr_stream_register_event(adsp_hdlr_stream_handle, param,
                                                      audio_extn_ip_hdlr_intf_event,
-                                                     handle);
+                                                     handle, is_adm_event);
     if (ret < 0) {
         ALOGE("%s:[%d] failed to register event %d",__func__, ip_hdlr->ref_cnt, ret);
         goto done;
@@ -363,12 +679,18 @@
     }
     ALOGD("%s:[%d] handle = %p, sess_handle = %p, is_dsp_decode = %d, usecase = %d",
           __func__, ip_hdlr->ref_cnt, handle, aud_sess_handle, is_dsp_decode, usecase);
-    if (is_dsp_decode) {
+    if (is_dsp_decode && ip_hdlr->asm_event) {
         ret = audio_extn_ip_hdlr_intf_open_dsp(handle, aud_sess_handle, usecase);
         if (ret < 0)
             ip_hdlr->close(handle);
     }
 
+    if (is_dsp_decode && ip_hdlr->adm_event) {
+        ret = audio_extn_ip_hdlr_intf_open_adm_event(handle, aud_sess_handle, usecase);
+        if (ret < 0)
+            ip_hdlr->close(handle);
+    }
+
     pthread_mutex_lock(&ip_hdlr->stream_list_lock);
     list_add_tail(&ip_hdlr->stream_list, &stream_info->list);
     pthread_mutex_unlock(&ip_hdlr->stream_list_lock);
@@ -430,10 +752,12 @@
                                  struct audio_device *dev, audio_usecase_t usecase)
 {
     int ret = 0, pcm_device_id;
-    int lib_fd;
+    struct lib_fd_info lib_fd;
     struct mixer_ctl *ctl = NULL;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
 
+    memset(&lib_fd, 0, sizeof(struct lib_fd_info));
+
     if (!ip_hdlr) {
         ip_hdlr = (struct ip_hdlr_intf *)calloc(1, sizeof(struct ip_hdlr_intf));
         if (!ip_hdlr)
@@ -451,44 +775,72 @@
         ip_hdlr->init =(int (*)(void **handle, char *lib_path,
                                 void **lib_handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_init");
         ip_hdlr->deinit = (int (*)(void *handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_deinit");
+        ip_hdlr->deinit_lib = (int (*)(void *handle))dlsym(ip_hdlr->lib_hdl,
+                                                "audio_ip_hdlr_deinit_lib");
         ip_hdlr->open = (int (*)(void *handle, bool is_dsp_decode,
                                  void *sess_handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_open");
         ip_hdlr->close =(int (*)(void *handle))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_close");
         ip_hdlr->reg_cb =(int (*)(void *handle, void *ack_cb,
                                   void *fail_cb))dlsym(ip_hdlr->lib_hdl, "audio_ip_hdlr_reg_cb");
-        ip_hdlr->shm_info =(int (*)(void *handle, int *fd))dlsym(ip_hdlr->lib_hdl,
-                                                                 "audio_ip_hdlr_shm_info");
+        ip_hdlr->shm_info =(int (*)(void *handle, int *fd))dlsym(
+                                   ip_hdlr->lib_hdl, "audio_ip_hdlr_shm_info");
+        ip_hdlr->shm_pp_info =(int (*)(void *handle, int *fd))dlsym(ip_hdlr->lib_hdl,
+                                                                 "audio_ip_hdlr_shm_pp_info");
         ip_hdlr->get_lib_fd =(int (*)(void *handle, int *fd))dlsym(ip_hdlr->lib_hdl,
                                                                  "audio_ip_hdlr_lib_fd");
         ip_hdlr->event =(int (*)(void *handle, void *payload))dlsym(ip_hdlr->lib_hdl,
                                                                     "audio_ip_hdlr_event");
+        ip_hdlr->event_adm =(int (*)(void *handle, void *payload))dlsym(
+                            ip_hdlr->lib_hdl, "audio_ip_hdlr_event_adm");
+        ip_hdlr->shm_pp = (int (*)(void *handle, bool is_adm_event))dlsym(
+                            ip_hdlr->lib_hdl, "audio_ip_hdlr_create_shm_pp");
         if (!ip_hdlr->init || !ip_hdlr->deinit || !ip_hdlr->open ||
             !ip_hdlr->close || !ip_hdlr->reg_cb || !ip_hdlr->shm_info ||
-            !ip_hdlr->event || !ip_hdlr->get_lib_fd) {
+            !ip_hdlr->event || !ip_hdlr->get_lib_fd || !ip_hdlr->deinit_lib ||
+            !ip_hdlr->shm_pp || !ip_hdlr->shm_pp_info || !ip_hdlr->event_adm) {
             ALOGE("%s: failed to get symbols", __func__);
             ret = -EINVAL;
             goto dlclose;
-
         }
     }
 
+    ip_hdlr->ip_dev_handle = dev;
     ret = ip_hdlr->init(handle, lib_path, lib_handle);
     if (ret < 0) {
         ALOGE("%s:[%d] init failed ret = %d", __func__, ip_hdlr->ref_cnt, ret);
         ret = -EINVAL;
         goto dlclose;
     }
-    if (!lib_path) {
-        ip_hdlr->get_lib_fd(*handle, &lib_fd);
 
-        pcm_device_id = platform_get_pcm_device_id(usecase, PCM_PLAYBACK);
+    if (adm_event_enable) {
+        ret = ip_hdlr->shm_pp(*handle, adm_event_enable);
+
+        if (ret < 0) {
+            ALOGE("%s:[%d] init failed ret = %d", __func__, ip_hdlr->ref_cnt, ret);
+            ret = -EINVAL;
+            goto dlclose;
+        }
+        ip_hdlr->adm_event = adm_event_enable;
+        adm_event_enable = false;
+    }
+
+    if (asm_event_enable) {
+        ip_hdlr->asm_event = asm_event_enable;
+        asm_event_enable = false;
+    }
+
+    if (!lib_path && !(ip_hdlr->lib_fd_created)) {
+        /* save handle to dlcose of lib fd */
+        ip_hdlr->ip_lib_handle = handle;
+        ip_hdlr->get_lib_fd(*handle, &lib_fd.fd);
+        lib_fd.flag = 1;
+        /* sending lib ion fd to routing driver */
         ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
-                       "Playback ION LIB FD %d", pcm_device_id);
+                       "ADSP ION LIB FD");
         if (ret < 0) {
             ALOGE("%s:[%d] snprintf failed %d", __func__, ip_hdlr->ref_cnt, ret);
             goto dlclose;
         }
-        ALOGV("%s: fd = %d  pcm_id = %d", __func__, lib_fd, pcm_device_id);
 
         ctl = mixer_get_ctl_by_name(dev->mixer, mixer_ctl_name);
         if (!ctl) {
@@ -497,12 +849,14 @@
             ret = -EINVAL;
             goto dlclose;
         }
-        ret = mixer_ctl_set_array(ctl, &lib_fd, sizeof(lib_fd));
+
+        ret = mixer_ctl_set_array(ctl, &lib_fd, sizeof(struct lib_fd_info));
         if (ret < 0) {
             ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d", __func__, ip_hdlr->ref_cnt,
                   mixer_ctl_name, ret);
             goto dlclose;
         }
+        ip_hdlr->lib_fd_created = true;
     }
     ip_hdlr->ref_cnt++;
     ALOGD("%s:[%d] init done", __func__, ip_hdlr->ref_cnt);
@@ -521,6 +875,12 @@
 int audio_extn_ip_hdlr_intf_deinit(void *handle)
 {
     int ret = 0;
+    struct lib_fd_info lib_fd;
+    struct mixer_ctl *ctl = NULL;
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    struct audio_device *ip_dev = (struct audio_device *) (ip_hdlr->ip_dev_handle);
+
+    memset(&lib_fd, 0, sizeof(struct lib_fd_info));
 
     if (!handle) {
         ALOGE("%s:[%d] handle is NULL", __func__, ip_hdlr->ref_cnt);
@@ -532,12 +892,41 @@
         ALOGE("%s:[%d] deinit failed ret = %d", __func__, ip_hdlr->ref_cnt, ret);
 
     if (--ip_hdlr->ref_cnt == 0) {
+        ip_hdlr->get_lib_fd(handle, &lib_fd.fd);
+        lib_fd.flag = 0;
+        /* sending lib ion fd to routing driver */
+        ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                       "ADSP ION LIB FD");
+        if (ret < 0) {
+            ALOGE("%s:[%d] snprintf failed %d"
+                , __func__, ip_hdlr->ref_cnt, ret);
+            goto dlclose;
+        }
+
+        ctl = mixer_get_ctl_by_name(ip_dev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s:[%d] Could not get ctl for mixer cmd - %s", __func__,
+                  ip_hdlr->ref_cnt, mixer_ctl_name);
+            ret = -EINVAL;
+            goto dlclose;
+        }
+        ret = mixer_ctl_set_array(ctl, &lib_fd, sizeof(struct lib_fd_info));
+        if (ret < 0) {
+            ALOGE("%s:[%d] Could not set ctl for mixer cmd - %s, ret %d"
+                        , __func__, ip_hdlr->ref_cnt, mixer_ctl_name, ret);
+            goto dlclose;
+        }
+
+        ret = ip_hdlr->deinit_lib(ip_hdlr->ip_lib_handle);
+        ip_hdlr->lib_fd_created = false;
         if (ip_hdlr->lib_hdl)
             dlclose(ip_hdlr->lib_hdl);
-
+dlclose:
         pthread_mutex_destroy(&ip_hdlr->stream_list_lock);
         free(ip_hdlr);
         ip_hdlr = NULL;
     }
+    ALOGD("%s: done\n", __func__);
     return ret;
+
 }
diff --git a/hal/audio_extn/ip_hdlr_intf.h b/hal/audio_extn/ip_hdlr_intf.h
index 6040620..5cfbc24 100644
--- a/hal/audio_extn/ip_hdlr_intf.h
+++ b/hal/audio_extn/ip_hdlr_intf.h
@@ -41,6 +41,8 @@
 bool audio_extn_ip_hdlr_intf_supported(audio_format_t format,
                                        bool is_direct_passthru,
                                        bool is_transcode_loopback);
+bool audio_extn_ip_hdlr_intf_supported_for_copp(void *platform);
+int audio_extn_ip_hdlr_copp_update_cal_info(void *cfg, void *data);
 
 #else
 
@@ -49,6 +51,8 @@
 #define audio_extn_ip_hdlr_intf_init(handle, lib_path, lib_handlei, adev, usecase)     (0)
 #define audio_extn_ip_hdlr_intf_deinit(handle)                                (0)
 #define audio_extn_ip_hdlr_intf_supported(format, is_direct_passthru, is_loopback) (0)
+#define audio_extn_ip_hdlr_intf_supported_for_copp(platform) (0)
+#define audio_extn_ip_hdlr_copp_update_cal_info(cfg, data) (0)
 
 #endif
 
diff --git a/hal/audio_extn/maxxaudio.c b/hal/audio_extn/maxxaudio.c
index 5f2a7f0..8830486 100644
--- a/hal/audio_extn/maxxaudio.c
+++ b/hal/audio_extn/maxxaudio.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2018-2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -156,12 +156,15 @@
 static uint16_t g_supported_dev = 0;
 static struct ma_state ma_cur_state_table[STREAM_MAX_TYPES];
 static struct ma_platform_data *my_data = NULL;
+// --- external function dependency ---
+fp_platform_set_parameters_t fp_platform_set_parameters;
+fp_audio_extn_get_snd_card_split_t fp_audio_extn_get_snd_card_split;
 
 static int set_audio_cal(const char *audio_cal)
 {
     ALOGV("set_audio_cal: %s", audio_cal);
 
-    return platform_set_parameters(my_data->platform,
+    return fp_platform_set_parameters(my_data->platform,
                                    str_parms_create_str(audio_cal));
 }
 
@@ -200,7 +203,7 @@
         ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
          (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
          (audio_is_usb_out_device(usecase->devices) &&
-          audio_extn_ma_supported_usb())))
+          ma_supported_usb())))
         /* TODO: enable A2DP when it is ready */
 
         return true;
@@ -390,7 +393,7 @@
 }
 
 // adev_init lock held
-void audio_extn_ma_init(void *platform)
+void ma_init(void *platform, maxx_audio_init_config_t init_config)
 {
     ma_stream_type_t i = 0;
     int ret = 0;
@@ -398,7 +401,11 @@
     char mps_path[128] = {0};
     char cnf_path[128] = {0};
     struct snd_card_split *snd_split_handle = NULL;
-    snd_split_handle = audio_extn_get_snd_card_split();
+
+    fp_platform_set_parameters = init_config.fp_platform_set_parameters;
+    fp_audio_extn_get_snd_card_split = init_config.fp_audio_extn_get_snd_card_split;
+
+    snd_split_handle = fp_audio_extn_get_snd_card_split();
 
     if (platform == NULL) {
         ALOGE("%s: platform is NULL", __func__);
@@ -549,7 +556,7 @@
 }
 
 //adev_init lock held
-void audio_extn_ma_deinit()
+void ma_deinit()
 {
     if (my_data) {
         /* deinit ma parameter */
@@ -566,7 +573,7 @@
 }
 
 // adev_init and adev lock held
-bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
+bool ma_set_state(struct audio_device *adev, int stream_type,
                              float vol, bool active)
 {
     bool ret = false;
@@ -613,7 +620,7 @@
     return ret;
 }
 
-void audio_extn_ma_set_device(struct audio_usecase *usecase)
+void ma_set_device(struct audio_usecase *usecase)
 {
     int i = 0;
     struct ma_audio_cal_settings ma_cal;
@@ -663,7 +670,7 @@
     pthread_mutex_unlock(&my_data->lock);
 }
 
-void audio_extn_ma_set_parameters(struct audio_device *adev,
+void ma_set_parameters(struct audio_device *adev,
                                   struct str_parms *parms)
 {
     int ret;
@@ -720,7 +727,7 @@
     }
 }
 
-bool audio_extn_ma_supported_usb()
+bool ma_supported_usb()
 {
     ALOGV("%s: current support 0x%x", __func__, g_supported_dev);
     return (g_supported_dev & SUPPORTED_USB) ? true : false;
diff --git a/hal/audio_extn/maxxaudio.h b/hal/audio_extn/maxxaudio.h
index 4c91107..1ab7f80 100644
--- a/hal/audio_extn/maxxaudio.h
+++ b/hal/audio_extn/maxxaudio.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2018-2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,23 +17,12 @@
 #ifndef MAXXAUDIO_H_
 #define MAXXAUDIO_H_
 
-#ifndef MAXXAUDIO_QDSP_ENABLED
-#define audio_extn_ma_init(platform)                                (0)
-#define audio_extn_ma_deinit()                                      (0)
-#define audio_extn_ma_set_state(adev, type, vol, active)            (false)
-#define audio_extn_ma_set_device(usecase)                           (0)
-#define audio_extn_ma_set_parameters(adev, param)                   (0)
-#define audio_extn_ma_supported_usb()                               (false)
-#else
-void audio_extn_ma_init(void *platform);
-void audio_extn_ma_deinit();
-bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
+void ma_init(void *platform, maxx_audio_init_config_t init_config);
+void ma_deinit();
+bool ma_set_state(struct audio_device *adev, int stream_type,
                              float vol, bool active);
-void audio_extn_ma_set_device(struct audio_usecase *usecase);
-void audio_extn_ma_set_parameters(struct audio_device *adev,
+void ma_set_device(struct audio_usecase *usecase);
+void ma_set_parameters(struct audio_device *adev,
                                   struct str_parms *parms);
-bool audio_extn_ma_supported_usb();
-#endif /* MAXXAUDIO_QDSP_ENABLED */
-
-#endif /* MAXXAUDIO_H_ */
-
+bool ma_supported_usb();
+#endif /* MAXXAUDIO_H_ */
\ No newline at end of file
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index c53fa31..4319174 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -966,7 +966,7 @@
 }
 
 static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
-{ 
+{
     struct audio_effect_config effect_config;
     struct audio_usecase *usecase = NULL;
     int ret = 0;
@@ -1189,6 +1189,14 @@
             goto err;
         }
 
+        if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
+             (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
+             (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
+            (audio_extn_sco_start_configuration() < 0)) {
+            ALOGE(" fail to configure sco control path ");
+            goto err;
+        }
+
         /* due to the possibility of calibration overwrite between listen
             and audio, notify listen hal before audio calibration is sent */
         audio_extn_sound_trigger_update_device_status(snd_device,
@@ -1281,7 +1289,14 @@
             audio_extn_a2dp_stop_playback();
         else if (snd_device == SND_DEVICE_IN_BT_A2DP)
             audio_extn_a2dp_stop_capture();
-        else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
+        else if ((snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
+                 (snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC) ||
+                 (snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB)) {
+            if ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_SCO_SWB] == 0) &&
+                (adev->snd_dev_ref_cnt[SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] == 0) &&
+                (adev->snd_dev_ref_cnt[SND_DEVICE_IN_BT_SCO_MIC_SWB] == 0))
+                audio_extn_sco_reset_configuration();
+       } else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
                 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
             adev->is_channel_status_set = false;
         else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
@@ -6698,7 +6713,7 @@
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
-    int ret = 0;
+    int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
     audio_format_t format;
     struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
     bool is_direct_passthough = false;
@@ -7447,7 +7462,8 @@
     is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
     if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
             (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
-            (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
+        audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
+        (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
         hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
                 out->usecase, PCM_PLAYBACK);
         hdlr_stream_cfg.flags = out->flags;
@@ -7459,7 +7475,10 @@
             out->adsp_hdlr_stream_handle = NULL;
         }
     }
-    if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
+    ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
+                                            is_direct_passthough, false);
+    ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
+    if (ip_hdlr_stream || ip_hdlr_dev ) {
         ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
@@ -7623,33 +7642,34 @@
             adev->screen_off = true;
     }
 
-#ifndef MAXXAUDIO_QDSP_ENABLED
-    ret = str_parms_get_int(parms, "rotation", &val);
-    if (ret >= 0) {
-        bool reverse_speakers = false;
-        switch(val) {
-        // FIXME: note that the code below assumes that the speakers are in the correct placement
-        //   relative to the user when the device is rotated 90deg from its default rotation. This
-        //   assumption is device-specific, not platform-specific like this code.
-        case 270:
-            reverse_speakers = true;
-            break;
-        case 0:
-        case 90:
-        case 180:
-            break;
-        default:
-            ALOGE("%s: unexpected rotation of %d", __func__, val);
-            status = -EINVAL;
+   if(!audio_extn_is_maxx_audio_enabled()) {
+        ret = str_parms_get_int(parms, "rotation", &val);
+        if (ret >= 0) {
+            bool reverse_speakers = false;
+            switch(val) {
+            // FIXME: note that the code below assumes that the speakers are
+            // in the correct placement relative to the user when the device
+            // is rotated 90deg from its default rotation. This assumption
+            // is device-specific, not platform-specific like this code.
+            case 270:
+                reverse_speakers = true;
+                break;
+            case 0:
+            case 90:
+            case 180:
+                break;
+            default:
+                ALOGE("%s: unexpected rotation of %d", __func__, val);
+                status = -EINVAL;
+            }
+            if (status == 0) {
+                // check and set swap
+                //   - check if orientation changed and speaker active
+                //   - set rotation and cache the rotation value
+                platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
+            }
         }
-        if (status == 0) {
-            // check and set swap
-            //   - check if orientation changed and speaker active
-            //   - set rotation and cache the rotation value
-            platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
-        }
-    }
-#endif
+   }
 
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
     if (ret >= 0) {
@@ -7659,6 +7679,12 @@
             adev->bt_wb_speech_enabled = false;
     }
 
+    ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
+    if (ret >= 0) {
+        val = atoi(value);
+        adev->swb_speech_mode = val;
+    }
+
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
     if (ret >= 0) {
         val = atoi(value);
@@ -9104,6 +9130,7 @@
 
     adev->enable_voicerx = false;
     adev->bt_wb_speech_enabled = false;
+    adev->swb_speech_mode = SPEECH_MODE_INVALID;
     //initialize this to false for now,
     //this will be set to true through set param
     adev->vr_audio_mode_enabled = false;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 1e7e1c5..1a04cff 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -85,6 +85,9 @@
 #define ACDB_DEV_TYPE_OUT 1
 #define ACDB_DEV_TYPE_IN 2
 
+/* SCO SWB codec mode */
+#define SPEECH_MODE_INVALID  0xFFFF
+
 /* support positional and index masks to 8ch */
 #define MAX_SUPPORTED_CHANNEL_MASKS (2 * FCC_8)
 #define MAX_SUPPORTED_FORMATS 15
@@ -527,6 +530,7 @@
     unsigned int cur_hdmi_bit_width;
     unsigned int cur_wfd_channels;
     bool bt_wb_speech_enabled;
+    unsigned int swb_speech_mode;
     bool allow_afe_proxy_usage;
     bool is_charging; // from battery listener
     bool mic_break_enabled;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 45fadf5..7b15f53 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -6159,7 +6159,6 @@
         ALOGV("%s: Format doesnt have to be set", __func__);
     }
 
-    format = format & AUDIO_FORMAT_MAIN_MASK;
     /* Set data format only if there is a change from PCM to compressed
        and vice versa */
     if (set_mi2s_tx_data_format && (format ^ my_data->current_backend_cfg[backend_idx].format)) {
@@ -6169,7 +6168,7 @@
                   __func__, ext_disp_format);
             return -EINVAL;
         }
-        if (format == AUDIO_FORMAT_PCM) {
+        if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
             ALOGE("%s:MI2S data format LPCM", __func__);
             mixer_ctl_set_enum_by_string(ctl, "LPCM");
         } else {
@@ -6724,18 +6723,25 @@
               __func__, bit_width, sample_rate, channels);
     }
 
-    ALOGI("%s:txbecf: afe: Codec selected backend: %d updated bit width: %d and "
-          "sample rate: %d", __func__, backend_idx, bit_width, sample_rate);
+    ALOGI("%s:txbecf: afe: current backend bit_width %d sample_rate %d channels %d, format %x",
+                            __func__,
+                            my_data->current_backend_cfg[backend_idx].bit_width,
+                            my_data->current_backend_cfg[backend_idx].sample_rate,
+                            my_data->current_backend_cfg[backend_idx].channels,
+                            my_data->current_backend_cfg[backend_idx].format);
     // Force routing if the expected bitwdith or samplerate
     // is not same as current backend comfiguration
+    // Note that below if block would be entered even if main format is same
+    // but subformat is different for e.g. current backend is configured for 16 bit PCM
+    // as compared to 24 bit PCM backend requested
     if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
         (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate) ||
         (channels != my_data->current_backend_cfg[backend_idx].channels) ||
-        ((format & AUDIO_FORMAT_MAIN_MASK) != my_data->current_backend_cfg[backend_idx].format)) {
+        (format != my_data->current_backend_cfg[backend_idx].format)) {
         backend_cfg->bit_width = bit_width;
         backend_cfg->sample_rate= sample_rate;
         backend_cfg->channels = channels;
-        backend_cfg->format = format & AUDIO_FORMAT_MAIN_MASK;
+        backend_cfg->format = format;
         backend_change = true;
         ALOGI("%s:txbecf: afe: Codec backend needs to be updated. new bit width: %d "
               "new sample rate: %d new channel: %d new format: %d",
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index 01df5bf..1c46ed7 100755
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -684,6 +684,10 @@
                  sizeof("sm6150-qrd-snd-card"))) {
         hw_info->is_stereo_spkr = false;
         strlcpy(hw_info->name, "sm6150", sizeof(hw_info->name));
+    } else if (!strncmp(snd_card_name, "sm6150-wcd9375qrd-snd-card",
+                 sizeof("sm6150-wcd9375qrd-snd-card"))) {
+        strlcpy(hw_info->name, "sm6150", sizeof(hw_info->name));
+        hw_info->is_stereo_spkr = false;
     } else if (!strncmp(snd_card_name, "sm6150-tavil-snd-card",
                  sizeof("sm6150-tavil-snd-card"))) {
         strlcpy(hw_info->name, "sm6150", sizeof(hw_info->name));
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index a428f9a..acd237e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -498,6 +498,7 @@
     [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = "speaker-and-display-port",
     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
     [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
+    [SND_DEVICE_OUT_BT_SCO_SWB] = "bt-sco-headset-swb",
     [SND_DEVICE_OUT_BT_A2DP] = "bt-a2dp",
     [SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = "speaker-and-bt-a2dp",
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = "speaker-safe-and-bt-a2dp",
@@ -544,9 +545,12 @@
     [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO] = "speaker-and-bt-sco",
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco",
     [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb",
+    [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_SWB] = "speaker-and-bt-sco-swb",
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb",
+    [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB] = "speaker-safe-and-bt-sco-swb",
     [SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO] = "wsa-speaker-and-bt-sco",
     [SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_WB] = "wsa-speaker-and-bt-sco-wb",
+    [SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_SWB] = "wsa-speaker-and-bt-sco-wb",
 
     /* Capture sound devices */
     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -593,6 +597,8 @@
     [SND_DEVICE_IN_BT_SCO_MIC_NREC] = "bt-sco-mic",
     [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
     [SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = "bt-sco-mic-wb",
+    [SND_DEVICE_IN_BT_SCO_MIC_SWB] = "bt-sco-mic-swb",
+    [SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] = "bt-sco-mic-swb",
     [SND_DEVICE_IN_BT_A2DP] = "bt-a2dp-cap",
     [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
     [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
@@ -751,7 +757,9 @@
     [SND_DEVICE_OUT_BT_SCO] = 22,
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = 14,
     [SND_DEVICE_OUT_BT_SCO_WB] = 39,
+    [SND_DEVICE_OUT_BT_SCO_SWB] = 39,
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = 14,
+    [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB] = 14,
     [SND_DEVICE_OUT_BT_A2DP] = 20,
     [SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = 14,
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = 14,
@@ -834,6 +842,8 @@
     [SND_DEVICE_IN_BT_SCO_MIC_NREC] = 122,
     [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
     [SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = 123,
+    [SND_DEVICE_IN_BT_SCO_MIC_SWB] = 38,
+    [SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] = 123,
     [SND_DEVICE_IN_BT_A2DP] = 21,
     [SND_DEVICE_IN_CAMCORDER_MIC] = 4,
     [SND_DEVICE_IN_VOICE_DMIC] = 41,
@@ -954,7 +964,9 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_SWB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_BT_A2DP)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)},
@@ -965,8 +977,10 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_SWB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_WB)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_SWB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_FULL_USB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_VCO_USB)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TX)},
@@ -1044,6 +1058,8 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_NREC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_WB)},
     {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_WB_NREC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_SWB)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_BT_A2DP)},
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC)},
@@ -1515,7 +1531,9 @@
          !strncmp(snd_card_name, "sdm439-sku1-snd-card",
                    sizeof("sdm439-sku1-snd-card")) ||
          !strncmp(snd_card_name, "sdm439-snd-card-mtp",
-                   sizeof("sdm439-snd-card-mtp"))) {
+                   sizeof("sdm439-snd-card-mtp")) ||
+         !strncmp(snd_card_name, "sm6150-wcd9375qrd-snd-card",
+                   sizeof("sm6150-wcd9375qrd-snd-card"))) {
          ALOGI("%s: snd_card_name: %s", __func__, snd_card_name);
          my_data->is_internal_codec = true;
          my_data->is_slimbus_interface = false;
@@ -1658,9 +1676,9 @@
 
     if (enable) {
         if (!voice_extn_is_compress_voip_supported()) {
-        if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
-            strlcat(ec_ref_mixer_path, "-voip", MIXER_PATH_MAX_LENGTH);
-        }        
+            if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
+                strlcat(ec_ref_mixer_path, "-voip", MIXER_PATH_MAX_LENGTH);
+        }
         strlcpy(my_data->ec_ref_mixer_path, ec_ref_mixer_path,
                     MIXER_PATH_MAX_LENGTH);
         /*
@@ -1894,11 +1912,14 @@
     backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
     backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("bt-sco");
     backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("bt-sco-wb");
+    backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_SWB] = strdup("bt-sco-swb");
+    backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] = strdup("bt-sco-swb");
     backend_tag_table[SND_DEVICE_IN_SPDIF] = strdup("spdif-in");
     backend_tag_table[SND_DEVICE_IN_HDMI_MIC] = strdup("hdmi-in");
     backend_tag_table[SND_DEVICE_IN_HDMI_ARC] = strdup("hdmi-arc-in");
     backend_tag_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
     backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
+    backend_tag_table[SND_DEVICE_OUT_BT_SCO_SWB] = strdup("bt-sco-swb");
     backend_tag_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
     backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
     backend_tag_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("display-port");
@@ -1920,6 +1941,8 @@
         strdup("speaker-safe-and-bt-sco");
     backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] =
         strdup("speaker-safe-and-bt-sco-wb");
+    backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB] =
+        strdup("speaker-safe-and-bt-sco-swb");
     backend_tag_table[SND_DEVICE_IN_VOICE_TTY_FULL_USB_MIC] = strdup("usb-headset-mic");
     backend_tag_table[SND_DEVICE_IN_VOICE_TTY_HCO_USB_MIC] = strdup("usb-headset-mic");
     backend_tag_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
@@ -1987,6 +2010,7 @@
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT");
     hw_interface_table[SND_DEVICE_OUT_BT_SCO] = strdup("SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("SLIMBUS_7_RX");
+    hw_interface_table[SND_DEVICE_OUT_BT_SCO_SWB] = strdup("SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_BT_A2DP] = strdup("SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("SLIMBUS_0_RX-and-SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] =
@@ -2020,8 +2044,10 @@
     hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = strdup("SLIMBUS_0_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX");
+    hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_SWB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX");
+    hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX");
     hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_PROTECTED] = strdup("SLIMBUS_0_RX");
     hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_STEREO_PROTECTED] = strdup("SLIMBUS_0_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = strdup("SLIMBUS_0_RX");
@@ -2076,6 +2102,8 @@
     hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("SLIMBUS_7_TX");
     hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("SLIMBUS_7_TX");
     hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("SLIMBUS_7_TX");
+    hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_SWB] = strdup("SLIMBUS_7_TX");
+    hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] = strdup("SLIMBUS_7_TX");
     hw_interface_table[SND_DEVICE_IN_BT_A2DP] = strdup("SLIMBUS_7_TX");
     hw_interface_table[SND_DEVICE_IN_CAMCORDER_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_DMIC] = strdup("SLIMBUS_0_TX");
@@ -2987,6 +3015,9 @@
     else if (!strncmp(snd_card_name, "sm6150-qrd-snd-card",
                sizeof("sm6150-qrd-snd-card")))
         platform_info_init(PLATFORM_INFO_XML_PATH_QRD, my_data, PLATFORM);
+    else if (!strncmp(snd_card_name, "sm6150-wcd9375qrd-snd-card",
+               sizeof("sm6150-wcd9375qrd-snd-card")))
+        platform_info_init(PLATFORM_INFO_XML_PATH_QRD, my_data, PLATFORM);
     else if (!strncmp(snd_card_name, "kona-qrd-snd-card",
                sizeof("kona-qrd-snd-card")))
         platform_info_init(PLATFORM_INFO_XML_PATH_QRD, my_data, PLATFORM);
@@ -4940,6 +4971,19 @@
         new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_SAFE;
         new_snd_devices[1] = SND_DEVICE_OUT_BT_SCO_WB;
         ret = 0;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_SWB &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_BT_SCO_SWB)) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+        new_snd_devices[1] = SND_DEVICE_OUT_BT_SCO_SWB;
+        ret = 0;
+    } else if (snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB &&
+               !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER_SAFE,
+                                              SND_DEVICE_OUT_BT_SCO_SWB)) {
+        *num_devices = 2;
+        new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_SAFE;
+        new_snd_devices[1] = SND_DEVICE_OUT_BT_SCO_SWB;
+        ret = 0;
     } else if (snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_USB_HEADSET &&
                !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER_SAFE, SND_DEVICE_OUT_USB_HEADSET)) {
         *num_devices = 2;
@@ -5131,19 +5175,29 @@
             snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP;
         } else if ((devices & AUDIO_DEVICE_OUT_ALL_SCO) &&
                    ((devices & ~AUDIO_DEVICE_OUT_ALL_SCO) == AUDIO_DEVICE_OUT_SPEAKER)) {
-            if (my_data->is_wsa_speaker)
-                snd_device = adev->bt_wb_speech_enabled ?
-                        SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_WB :
-                        SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO;
-            else
-                snd_device = adev->bt_wb_speech_enabled ?
-                        SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB :
-                        SND_DEVICE_OUT_SPEAKER_AND_BT_SCO;
+            if (my_data->is_wsa_speaker) {
+                if (adev->swb_speech_mode != SPEECH_MODE_INVALID)
+                    snd_device = SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_SWB;
+                else
+                    snd_device = adev->bt_wb_speech_enabled ?
+                            SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_WB :
+                            SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO;
+            } else {
+                if (adev->swb_speech_mode != SPEECH_MODE_INVALID)
+                    snd_device = SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_SWB;
+                else
+                    snd_device = adev->bt_wb_speech_enabled ?
+                            SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB :
+                            SND_DEVICE_OUT_SPEAKER_AND_BT_SCO;
+            }
         } else if ((devices & AUDIO_DEVICE_OUT_ALL_SCO) &&
                          ((devices & ~AUDIO_DEVICE_OUT_ALL_SCO) == AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-            snd_device = adev->bt_wb_speech_enabled ?
-                    SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB :
-                    SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO;
+            if (adev->swb_speech_mode != SPEECH_MODE_INVALID)
+                snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB;
+            else
+                snd_device = adev->bt_wb_speech_enabled ?
+                        SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB :
+                        SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO;
         } else if ((devices == (AUDIO_DEVICE_OUT_USB_DEVICE |
                                AUDIO_DEVICE_OUT_SPEAKER_SAFE)) ||
                 (devices == (AUDIO_DEVICE_OUT_USB_HEADSET |
@@ -5225,7 +5279,9 @@
                                  SND_DEVICE_OUT_VOICE_USB_HEADPHONES;
             }
         } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
-            if (adev->bt_wb_speech_enabled)
+            if (adev->swb_speech_mode != SPEECH_MODE_INVALID)
+                snd_device = SND_DEVICE_OUT_BT_SCO_SWB;
+            else if (adev->bt_wb_speech_enabled)
                 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
             else
                 snd_device = SND_DEVICE_OUT_BT_SCO;
@@ -5351,7 +5407,9 @@
         else
             snd_device = SND_DEVICE_OUT_SPEAKER;
     } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
-        if (adev->bt_wb_speech_enabled)
+        if (adev->swb_speech_mode != SPEECH_MODE_INVALID)
+                snd_device = SND_DEVICE_OUT_BT_SCO_SWB;
+        else if (adev->bt_wb_speech_enabled)
             snd_device = SND_DEVICE_OUT_BT_SCO_WB;
         else
             snd_device = SND_DEVICE_OUT_BT_SCO;
@@ -5740,7 +5798,12 @@
             if (audio_extn_hfp_is_active(adev))
                 platform_set_echo_reference(adev, true, out_device);
         } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
-            if (adev->bt_wb_speech_enabled) {
+            if (adev->swb_speech_mode != SPEECH_MODE_INVALID) {
+                if (adev->bluetooth_nrec)
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC;
+                else
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_SWB;
+            } else if (adev->bt_wb_speech_enabled) {
                 if (adev->bluetooth_nrec)
                     snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB_NREC;
                 else
@@ -6050,7 +6113,12 @@
         } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
             snd_device = SND_DEVICE_IN_HEADSET_MIC;
         } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-            if (adev->bt_wb_speech_enabled) {
+            if (adev->swb_speech_mode != SPEECH_MODE_INVALID) {
+                if (adev->bluetooth_nrec)
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC;
+                else
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_SWB;
+            } else if (adev->bt_wb_speech_enabled) {
                 if (adev->bluetooth_nrec)
                     snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB_NREC;
                 else
@@ -6113,7 +6181,12 @@
             snd_device = my_data->fluence_sb_enabled ? SND_DEVICE_IN_HANDSET_MIC_SB
                              : SND_DEVICE_IN_HANDSET_MIC;
         } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
-            if (adev->bt_wb_speech_enabled) {
+            if (adev->swb_speech_mode != SPEECH_MODE_INVALID) {
+                if (adev->bluetooth_nrec)
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC;
+                else
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_SWB;
+            } else if (adev->bt_wb_speech_enabled) {
                 if (adev->bluetooth_nrec)
                     snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB_NREC;
                 else
@@ -7389,7 +7462,6 @@
     int ret = -EINVAL;
     int backend_idx = platform_get_backend_index(snd_device);
     struct platform_data *my_data = (struct platform_data *)adev->platform;
-    backend_idx = platform_get_backend_index(snd_device);
     unsigned int bit_width = backend_cfg.bit_width;
     unsigned int sample_rate = backend_cfg.sample_rate;
     unsigned int channels = backend_cfg.channels;
@@ -7611,7 +7683,6 @@
         ALOGV("%s: Format doesnt have to be set", __func__);
     }
 
-    format = format & AUDIO_FORMAT_MAIN_MASK;
     /* Set data format only if there is a change from PCM to compressed
        and vice versa */
     if (set_mi2s_tx_data_format && (format ^ my_data->current_backend_cfg[backend_idx].format)) {
@@ -7621,7 +7692,7 @@
                   __func__, ext_disp_format);
             return -EINVAL;
         }
-        if (format == AUDIO_FORMAT_PCM) {
+        if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
             ALOGE("%s:Set %s to LPCM", __func__, ext_disp_format);
             mixer_ctl_set_enum_by_string(ctl, "LPCM");
         } else {
@@ -7790,6 +7861,7 @@
     if (snd_device == SND_DEVICE_OUT_BT_A2DP ||
         snd_device == SND_DEVICE_OUT_BT_SCO ||
         snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
+        snd_device == SND_DEVICE_OUT_BT_SCO_SWB ||
         snd_device == SND_DEVICE_IN_BT_A2DP ||
         snd_device == SND_DEVICE_OUT_AFE_PROXY) {
         backend_change = false;
@@ -8193,18 +8265,25 @@
               __func__, bit_width, sample_rate, channels);
     }
 
-    ALOGI("%s:txbecf: afe: Codec selected backend: %d updated bit width: %d and "
-          "sample rate: %d", __func__, backend_idx, bit_width, sample_rate);
+    ALOGI("%s:txbecf: afe: current backend bit_width %d sample_rate %d channels %d, format %x",
+                            __func__,
+                            my_data->current_backend_cfg[backend_idx].bit_width,
+                            my_data->current_backend_cfg[backend_idx].sample_rate,
+                            my_data->current_backend_cfg[backend_idx].channels,
+                            my_data->current_backend_cfg[backend_idx].format);
     // Force routing if the expected bitwdith or samplerate
     // is not same as current backend comfiguration
+    // Note that below if block would be entered even if main format is same
+    // but subformat is different for e.g. current backend is configured for 16 bit PCM
+    // as compared to 24 bit PCM backend requested
     if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
         (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate) ||
         (channels != my_data->current_backend_cfg[backend_idx].channels) ||
-        ((format & AUDIO_FORMAT_MAIN_MASK) != my_data->current_backend_cfg[backend_idx].format)) {
+        (format != my_data->current_backend_cfg[backend_idx].format)) {
         backend_cfg->bit_width = bit_width;
         backend_cfg->sample_rate= sample_rate;
         backend_cfg->channels = channels;
-        backend_cfg->format = format & AUDIO_FORMAT_MAIN_MASK;
+        backend_cfg->format = format;
         backend_change = true;
         ALOGI("%s:txbecf: afe: Codec backend needs to be updated. new bit width: %d "
               "new sample rate: %d new channel: %d new format: %d",
@@ -9571,6 +9650,9 @@
         ret = -EINVAL;
         goto ERROR_RETURN;
     }
+    if ((cal->acdb_dev_id == ACDB_ID_STEREO_SPEAKER_DEVICE) &&
+       (cal->topo_id == TRUMPET_TOPOLOGY))
+        audio_extn_ip_hdlr_copp_update_cal_info((void*)cal, data);
 
     if (my_data->acdb_set_audio_cal) {
         // persist audio cal in local cache
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 2cb1741..6203cf8 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -21,6 +21,9 @@
 #define QCOM_AUDIO_PLATFORM_H
 #include <sound/voice_params.h>
 
+#define TRUMPET_TOPOLOGY 0x11000099
+#define ACDB_ID_STEREO_SPEAKER_DEVICE 15
+
 enum {
     FLUENCE_NONE,
     FLUENCE_DUAL_MIC = 0x1,
@@ -110,6 +113,7 @@
     SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
     SND_DEVICE_OUT_BT_SCO,
     SND_DEVICE_OUT_BT_SCO_WB,
+    SND_DEVICE_OUT_BT_SCO_SWB,
     SND_DEVICE_OUT_BT_A2DP,
     SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP,
     SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP,
@@ -118,8 +122,11 @@
     SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO,
     SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB,
     SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB,
+    SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_SWB,
+    SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_SWB,
     SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO,
     SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_WB,
+    SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_SWB,
     SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES,
     SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES,
     SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET,
@@ -219,6 +226,8 @@
     SND_DEVICE_IN_BT_SCO_MIC_NREC,
     SND_DEVICE_IN_BT_SCO_MIC_WB,
     SND_DEVICE_IN_BT_SCO_MIC_WB_NREC,
+    SND_DEVICE_IN_BT_SCO_MIC_SWB,
+    SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC,
     SND_DEVICE_IN_BT_A2DP,
     SND_DEVICE_IN_CAMCORDER_MIC,
     SND_DEVICE_IN_VOICE_DMIC,