Merge "configs: apq8098_latv: propagate msm8998 changes"
diff --git a/configs/apq8098_latv/apq8098_latv.mk b/configs/apq8098_latv/apq8098_latv.mk
index cc17043..4d20981 100755
--- a/configs/apq8098_latv/apq8098_latv.mk
+++ b/configs/apq8098_latv/apq8098_latv.mk
@@ -46,7 +46,7 @@
 AUDIO_FEATURE_ENABLED_FLUENCE := true
 AUDIO_FEATURE_ENABLED_HDMI_EDID := true
 AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
-#AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
+AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
 AUDIO_FEATURE_ENABLED_DISPLAY_PORT := true
 AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := false
 AUDIO_FEATURE_ENABLED_HFP := true
@@ -56,6 +56,7 @@
 AUDIO_FEATURE_ENABLED_SPKR_PROTECTION := true
 AUDIO_FEATURE_ENABLED_ACDB_LICENSE := true
 AUDIO_FEATURE_ENABLED_DEV_ARBI := false
+AUDIO_FEATURE_ENABLED_DYNAMIC_LOG := true
 MM_AUDIO_ENABLED_FTM := true
 TARGET_USES_QCOM_MM_AUDIO := true
 AUDIO_FEATURE_ENABLED_SOURCE_TRACKING := true
diff --git a/configs/apq8098_latv/audio_policy_configuration.xml b/configs/apq8098_latv/audio_policy_configuration.xml
index fafd322..484f96a 100755
--- a/configs/apq8098_latv/audio_policy_configuration.xml
+++ b/configs/apq8098_latv/audio_policy_configuration.xml
@@ -68,6 +68,10 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
                 <mixPort name="deep_buffer" role="source"
                         flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
@@ -194,6 +198,11 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
                 </mixPort>
+                <mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3"/>
+                </mixPort>
             </mixPorts>
 
             <devicePorts>
@@ -305,15 +314,15 @@
             <!-- route declaration, i.e. list all available sources for a given sink -->
             <routes>
                 <route type="mix" sink="Earpiece"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="Speaker"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="Wired Headset"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,dsd_compress_passthrough,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,dsd_compress_passthrough,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="Wired Headphones"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,dsd_compress_passthrough,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,dsd_compress_passthrough,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="Line"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,dsd_compress_passthrough,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,dsd_compress_passthrough,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="HDMI"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,compress_passthrough"/>
                 <route type="mix" sink="Proxy"
@@ -321,9 +330,9 @@
                 <route type="mix" sink="FM"
                        sources="primary output"/>
                 <route type="mix" sink="BT SCO All"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="USB Device Out"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="Telephony Tx"
                        sources="voice_tx"/>
                 <route type="mix" sink="voice_rx"
@@ -334,6 +343,8 @@
                        sources="Built-In Mic,Built-In Back Mic"/>
                 <route type="mix" sink="record_24"
                        sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic"/>
+                <route type="mix" sink="mmap_no_irq_in"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,USB Device In"/>
                 <route type="mix" sink="BT A2DP Out"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
                 <route type="mix" sink="BT A2DP Headphones"
diff --git a/configs/msm8998/audio_policy_configuration.xml b/configs/msm8998/audio_policy_configuration.xml
index e084bba..e2ec755 100644
--- a/configs/msm8998/audio_policy_configuration.xml
+++ b/configs/msm8998/audio_policy_configuration.xml
@@ -77,6 +77,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="hifi_playback" role="source" />
                 <mixPort name="compress_passthrough" role="source"
                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
                     <profile name="" format="dynamic"
@@ -200,6 +201,7 @@
                              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3"/>
                 </mixPort>
+                <mixPort name="hifi_input" role="sink" />
             </mixPorts>
 
             <devicePorts>
@@ -329,7 +331,7 @@
                 <route type="mix" sink="BT SCO All"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
                 <route type="mix" sink="USB Device Out"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback"/>
                 <route type="mix" sink="Telephony Tx"
                        sources="voice_tx"/>
                 <route type="mix" sink="voice_rx"
@@ -348,6 +350,7 @@
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
                 <route type="mix" sink="BT A2DP Speaker"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
+                <route type="mix" sink="hifi_input" sources="USB Device In" />
             </routes>
 
         </module>
diff --git a/configs/msm8998/mixer_paths_skuk.xml b/configs/msm8998/mixer_paths_skuk.xml
index e4b3785..f2e9c9a 100644
--- a/configs/msm8998/mixer_paths_skuk.xml
+++ b/configs/msm8998/mixer_paths_skuk.xml
@@ -165,6 +165,7 @@
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="0" />
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="0" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia6 Mixer SLIM_0_TX" value="0" />
@@ -204,6 +205,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2594,4 +2596,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/msm8998/mixer_paths_tasha.xml b/configs/msm8998/mixer_paths_tasha.xml
index 93656e6..4ea726b 100644
--- a/configs/msm8998/mixer_paths_tasha.xml
+++ b/configs/msm8998/mixer_paths_tasha.xml
@@ -212,6 +212,7 @@
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="0" />
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="0" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia6 Mixer SLIM_0_TX" value="0" />
@@ -389,6 +390,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2935,4 +2937,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/msm8998/mixer_paths_tavil.xml b/configs/msm8998/mixer_paths_tavil.xml
index ba37799..fc5a440 100644
--- a/configs/msm8998/mixer_paths_tavil.xml
+++ b/configs/msm8998/mixer_paths_tavil.xml
@@ -173,6 +173,7 @@
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="0" />
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="0" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia6 Mixer SLIM_0_TX" value="0" />
@@ -212,6 +213,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2801,4 +2803,24 @@
        <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
     </path>
 
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/audio_platform_info.xml b/configs/sdm660/audio_platform_info.xml
index 313c59b..b5aa892 100644
--- a/configs/sdm660/audio_platform_info.xml
+++ b/configs/sdm660/audio_platform_info.xml
@@ -76,6 +76,7 @@
     </config_params>
     <acdb_ids>
         <device name="SND_DEVICE_OUT_SPEAKER" acdb_id="15"/>
+        <device name="SND_DEVICE_OUT_SPEAKER_REVERSE" acdb_id="15"/>
         <device name="SND_DEVICE_OUT_SPEAKER_PROTECTED" acdb_id="124"/>
         <device name="SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED" acdb_id="101"/>
         <device name="SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT" acdb_id="124"/>
diff --git a/configs/sdm660/audio_policy_configuration.xml b/configs/sdm660/audio_policy_configuration.xml
index 9a67a32..418cf42 100644
--- a/configs/sdm660/audio_policy_configuration.xml
+++ b/configs/sdm660/audio_policy_configuration.xml
@@ -73,6 +73,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="hifi_playback" role="source" />
                 <mixPort name="compress_passthrough" role="source"
                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
                     <profile name="" format="dynamic"
@@ -191,6 +192,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
                 </mixPort>
+                <mixPort name="hifi_input" role="sink" />
             </mixPorts>
 
             <devicePorts>
@@ -320,7 +322,7 @@
                 <route type="mix" sink="BT SCO All"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
                 <route type="mix" sink="USB Device Out"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,hifi_playback"/>
                 <route type="mix" sink="Telephony Tx"
                        sources="voice_tx"/>
                 <route type="mix" sink="voice_rx"
@@ -337,6 +339,7 @@
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
                 <route type="mix" sink="BT A2DP Speaker"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
+                <route type="mix" sink="hifi_input" sources="USB Device In" />
             </routes>
 
         </module>
diff --git a/configs/sdm660/mixer_paths.xml b/configs/sdm660/mixer_paths.xml
index 459ffa1..8cca459 100644
--- a/configs/sdm660/mixer_paths.xml
+++ b/configs/sdm660/mixer_paths.xml
@@ -147,6 +147,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -175,6 +176,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2312,4 +2314,25 @@
     <path name="mmap-record usb-headset-mic">
        <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths_mtp.xml b/configs/sdm660/mixer_paths_mtp.xml
index bba3cb9..4f61224 100644
--- a/configs/sdm660/mixer_paths_mtp.xml
+++ b/configs/sdm660/mixer_paths_mtp.xml
@@ -146,6 +146,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -174,6 +175,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2373,4 +2375,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths_skus.xml b/configs/sdm660/mixer_paths_skus.xml
index 8ecc1a3..bdd0d61 100644
--- a/configs/sdm660/mixer_paths_skus.xml
+++ b/configs/sdm660/mixer_paths_skus.xml
@@ -210,6 +210,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -391,6 +392,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2849,4 +2851,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths_skush.xml b/configs/sdm660/mixer_paths_skush.xml
index cf0838f..aa81e7b 100644
--- a/configs/sdm660/mixer_paths_skush.xml
+++ b/configs/sdm660/mixer_paths_skush.xml
@@ -141,6 +141,7 @@
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="0" />
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="0" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia6 Mixer INT3_MI2S_TX" value="0" />
@@ -166,6 +167,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2423,4 +2425,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths_wcd9326.xml b/configs/sdm660/mixer_paths_wcd9326.xml
index 0745180..9e6623d 100644
--- a/configs/sdm660/mixer_paths_wcd9326.xml
+++ b/configs/sdm660/mixer_paths_wcd9326.xml
@@ -209,6 +209,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -390,6 +391,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2794,4 +2796,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths_wcd9335.xml b/configs/sdm660/mixer_paths_wcd9335.xml
index 8cc6f65..d4c098f 100644
--- a/configs/sdm660/mixer_paths_wcd9335.xml
+++ b/configs/sdm660/mixer_paths_wcd9335.xml
@@ -209,6 +209,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -390,6 +391,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2871,4 +2873,25 @@
     <path name="mmap-record usb-headset-mic">
        <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths_wcd9340.xml b/configs/sdm660/mixer_paths_wcd9340.xml
index 213f5c3..6c6f2cf 100644
--- a/configs/sdm660/mixer_paths_wcd9340.xml
+++ b/configs/sdm660/mixer_paths_wcd9340.xml
@@ -170,6 +170,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -213,6 +214,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2619,4 +2621,24 @@
        <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
     </path>
 
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/sdm660.mk b/configs/sdm660/sdm660.mk
index 8d57a46..6834479 100644
--- a/configs/sdm660/sdm660.mk
+++ b/configs/sdm660/sdm660.mk
@@ -57,6 +57,7 @@
 AUDIO_FEATURE_ENABLED_SPKR_PROTECTION := true
 AUDIO_FEATURE_ENABLED_ACDB_LICENSE := true
 AUDIO_FEATURE_ENABLED_DEV_ARBI := false
+AUDIO_FEATURE_ENABLED_DYNAMIC_LOG := true
 MM_AUDIO_ENABLED_FTM := true
 TARGET_USES_QCOM_MM_AUDIO := true
 AUDIO_FEATURE_ENABLED_SOURCE_TRACKING := true
diff --git a/configs/sdm670/audio_platform_info.xml b/configs/sdm670/audio_platform_info.xml
index 57cddc2..71a8bf6 100644
--- a/configs/sdm670/audio_platform_info.xml
+++ b/configs/sdm670/audio_platform_info.xml
@@ -41,6 +41,24 @@
         <device name="SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2" acdb_id="10"/>
         <device name="SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET" acdb_id="45"/>
     </acdb_ids>
+    <module_ids>
+        <aec>
+            <device name="SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS" module_id="0x10F17" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE" module_id="0x10F18" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_SPEAKER_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_HANDSET_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_HANDSET_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+        </aec>
+        <ns>
+            <device name="SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS" module_id="0x10F17" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE" module_id="0x10F18" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_SPEAKER_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_HANDSET_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_HANDSET_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+        </ns>
+    </module_ids>
     <bit_width_configs>
         <device name="SND_DEVICE_OUT_SPEAKER" bit_width="24"/>
     </bit_width_configs>
diff --git a/configs/sdm670/audio_policy_configuration.xml b/configs/sdm670/audio_policy_configuration.xml
index 09a4bb9..8e51ba5 100644
--- a/configs/sdm670/audio_policy_configuration.xml
+++ b/configs/sdm670/audio_policy_configuration.xml
@@ -73,6 +73,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="hifi_playback" role="source" />
                 <mixPort name="compress_passthrough" role="source"
                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
                     <profile name="" format="dynamic"
@@ -191,6 +192,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
                 </mixPort>
+                <mixPort name="hifi_input" role="sink" />
             </mixPorts>
 
             <devicePorts>
@@ -320,7 +322,7 @@
                 <route type="mix" sink="BT SCO All"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
                 <route type="mix" sink="USB Device Out"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,hifi_playback"/>
                 <route type="mix" sink="Telephony Tx"
                        sources="voice_tx"/>
                 <route type="mix" sink="voice_rx"
@@ -337,6 +339,7 @@
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
                 <route type="mix" sink="BT A2DP Speaker"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
+                <route type="mix" sink="hifi_input" sources="USB Device In" />
             </routes>
 
         </module>
diff --git a/configs/sdm670/mixer_paths.xml b/configs/sdm670/mixer_paths.xml
index 1b07f80..5f81e65 100644
--- a/configs/sdm670/mixer_paths.xml
+++ b/configs/sdm670/mixer_paths.xml
@@ -146,6 +146,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -174,6 +175,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2256,4 +2258,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm670/mixer_paths_mtp.xml b/configs/sdm670/mixer_paths_mtp.xml
index b08059c..9b462a4 100644
--- a/configs/sdm670/mixer_paths_mtp.xml
+++ b/configs/sdm670/mixer_paths_mtp.xml
@@ -132,6 +132,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -159,6 +160,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2119,4 +2121,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm670/mixer_paths_tasha.xml b/configs/sdm670/mixer_paths_tasha.xml
index be2f56b..cbb74a5 100644
--- a/configs/sdm670/mixer_paths_tasha.xml
+++ b/configs/sdm670/mixer_paths_tasha.xml
@@ -195,6 +195,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -375,6 +376,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2751,4 +2753,24 @@
         <path name="audio-ull-playback" />
     </path>
 
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm670/mixer_paths_tashalite.xml b/configs/sdm670/mixer_paths_tashalite.xml
index 65dec6a..e4ea674 100644
--- a/configs/sdm670/mixer_paths_tashalite.xml
+++ b/configs/sdm670/mixer_paths_tashalite.xml
@@ -195,6 +195,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -375,6 +376,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2728,4 +2730,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm670/mixer_paths_tavil.xml b/configs/sdm670/mixer_paths_tavil.xml
index 8a8783b..f822423 100644
--- a/configs/sdm670/mixer_paths_tavil.xml
+++ b/configs/sdm670/mixer_paths_tavil.xml
@@ -157,6 +157,7 @@
     <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
     <ctl name="USB_AUDIO_RX Channels" value="Two" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
@@ -199,6 +200,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2386,4 +2388,25 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm670/sdm670.mk b/configs/sdm670/sdm670.mk
index 7efcc2f..d220650 100644
--- a/configs/sdm670/sdm670.mk
+++ b/configs/sdm670/sdm670.mk
@@ -7,6 +7,7 @@
 USE_CUSTOM_AUDIO_POLICY := 1
 AUDIO_FEATURE_ENABLED_COMPRESS_CAPTURE := false
 AUDIO_FEATURE_ENABLED_COMPRESS_VOIP := true
+AUDIO_FEATURE_ENABLED_DYNAMIC_ECNS := false
 AUDIO_FEATURE_ENABLED_EXTN_FORMATS := true
 AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER := true
 AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER := true
@@ -23,6 +24,7 @@
 AUDIO_FEATURE_ENABLED_PROXY_DEVICE := true
 AUDIO_FEATURE_ENABLED_SSR := true
 AUDIO_FEATURE_ENABLED_DTS_EAGLE := false
+AUDIO_FEATURE_ENABLED_DYNAMIC_LOG := true
 BOARD_USES_SRS_TRUEMEDIA := false
 DTS_CODEC_M_ := false
 MM_AUDIO_ENABLED_SAFX := true
@@ -98,7 +100,7 @@
     hardware/qcom/audio/configs/sdm670/sound_trigger_mixer_paths_wcd9335.xml:$(TARGET_COPY_OUT_VENDOR)/etc/sound_trigger_mixer_paths_wcd9335.xml \
     hardware/qcom/audio/configs/sdm670/sound_trigger_mixer_paths_wcd9340.xml:$(TARGET_COPY_OUT_VENDOR)/etc/sound_trigger_mixer_paths_wcd9340.xml \
     hardware/qcom/audio/configs/sdm670/sound_trigger_mixer_paths_wcd9340.xml:$(TARGET_COPY_OUT_VENDOR)/etc/sound_trigger_mixer_paths_wcd9340.xml \
-    hardware/qcom/audio/configs/sdm670/graphite_ipc_platform_info.xml:$(TARGET_COPY_OUT_VENDOR)/etc/graphite_ipc_platform_info.xml \
+    hardware/qcom/audio/configs/sdm670/graphite_ipc_platform_info.xml:$(TARGET_COPY_OUT_VENDOR)/etc/graphite_ipc_platform_info.xml
 
 #XML Audio configuration files
 ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
diff --git a/configs/sdm845/audio_platform_info.xml b/configs/sdm845/audio_platform_info.xml
index d53fce8..19ea80c 100644
--- a/configs/sdm845/audio_platform_info.xml
+++ b/configs/sdm845/audio_platform_info.xml
@@ -27,6 +27,7 @@
 <audio_platform_info>
     <acdb_ids>
         <device name="SND_DEVICE_OUT_SPEAKER" acdb_id="15"/>
+        <device name="SND_DEVICE_OUT_SPEAKER_REVERSE" acdb_id="15"/>
         <device name="SND_DEVICE_OUT_SPEAKER_PROTECTED" acdb_id="124"/>
         <device name="SND_DEVICE_IN_VOICE_REC_QMIC_FLUENCE" acdb_id="131"/>
         <device name="SND_DEVICE_IN_VOICE_REC_TMIC" acdb_id="131"/>
@@ -35,8 +36,33 @@
         <device name="SND_DEVICE_OUT_VOICE_SPEAKER_2_PROTECTED_VBAT" acdb_id="150"/>
         <device name="SND_DEVICE_IN_CAPTURE_VI_FEEDBACK_MONO_1" acdb_id="151"/>
         <device name="SND_DEVICE_IN_CAPTURE_VI_FEEDBACK_MONO_2" acdb_id="152"/>
-	<device name="SND_DEVICE_IN_UNPROCESSED_USB_HEADSET_MIC" acdb_id="133"/>
+        <device name="SND_DEVICE_IN_UNPROCESSED_USB_HEADSET_MIC" acdb_id="133"/>
+        <device name="SND_DEVICE_IN_UNPROCESSED_MIC" acdb_id="143"/>
+        <device name="SND_DEVICE_IN_UNPROCESSED_STEREO_MIC" acdb_id="144"/>
+        <device name="SND_DEVICE_IN_UNPROCESSED_THREE_MIC" acdb_id="145"/>
+        <device name="SND_DEVICE_IN_UNPROCESSED_QUAD_MIC" acdb_id="146"/>
+        <device name="SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC" acdb_id="147"/>
     </acdb_ids>
+
+    <module_ids>
+        <aec>
+            <device name="SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS" module_id="0x10F17" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE" module_id="0x10F18" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_SPEAKER_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_HANDSET_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+            <device name="SND_DEVICE_IN_HANDSET_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x01"/>
+        </aec>
+        <ns>
+            <device name="SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS" module_id="0x10F17" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE" module_id="0x10F18" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_SPEAKER_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_HANDSET_DMIC_AEC_NS" module_id="0x10F0A" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+            <device name="SND_DEVICE_IN_HANDSET_MIC_AEC_NS" module_id="0x10F09" instance_id="0x0" param_id="0x10EAF" param_value="0x02"/>
+        </ns>
+    </module_ids>
+
     <bit_width_configs>
         <device name="SND_DEVICE_OUT_SPEAKER" bit_width="24"/>
     </bit_width_configs>
diff --git a/configs/sdm845/audio_policy_configuration.xml b/configs/sdm845/audio_policy_configuration.xml
index d775641..a19151c 100644
--- a/configs/sdm845/audio_policy_configuration.xml
+++ b/configs/sdm845/audio_policy_configuration.xml
@@ -77,6 +77,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="hifi_playback" role="source" />
                 <mixPort name="compress_passthrough" role="source"
                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
                     <profile name="" format="dynamic"
@@ -200,6 +201,7 @@
                              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3"/>
                 </mixPort>
+                <mixPort name="hifi_input" role="sink" />
             </mixPorts>
 
             <devicePorts>
@@ -329,7 +331,7 @@
                 <route type="mix" sink="BT SCO All"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
                 <route type="mix" sink="USB Device Out"
-                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out"/>
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback"/>
                 <route type="mix" sink="Telephony Tx"
                        sources="voice_tx"/>
                 <route type="mix" sink="voice_rx"
@@ -348,6 +350,7 @@
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
                 <route type="mix" sink="BT A2DP Speaker"
                        sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload"/>
+                <route type="mix" sink="hifi_input" sources="USB Device In" />
             </routes>
 
         </module>
diff --git a/configs/sdm845/mixer_paths_tavil.xml b/configs/sdm845/mixer_paths_tavil.xml
index b073fb2..8a6360b 100644
--- a/configs/sdm845/mixer_paths_tavil.xml
+++ b/configs/sdm845/mixer_paths_tavil.xml
@@ -154,6 +154,7 @@
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="0" />
     <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="0" />
     <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+    <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
     <ctl name="MultiMedia10 Mixer USB_AUDIO_TX" value="0" />
@@ -193,6 +194,7 @@
     <ctl name="AUDIO_REF_EC_UL1 MUX" value="None" />
     <!-- usb headset -->
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia1" value="0" />
+    <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia7" value="0" />
     <ctl name="AFE_PCM_RX Audio Mixer MultiMedia10" value="0" />
@@ -2431,6 +2433,22 @@
         <path name="unprocessed-handset-mic" />
     </path>
 
+    <path name="unprocessed-stereo-mic">
+        <path name="voice-rec-dmic-ef" />
+    </path>
+
+    <path name="unprocessed-three-mic">
+        <path name="three-mic" />
+    </path>
+
+    <path name="unprocessed-quad-mic">
+        <path name="quad-mic" />
+    </path>
+
+    <path name="unprocessed-headset-mic">
+        <path name="headset-mic" />
+    </path>
+
     <!-- USB TTY start -->
 
     <!-- full: both end tty -->
@@ -2658,4 +2676,24 @@
        <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
     </path>
 
+    <path name="hifi-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="1" />
+    </path>
+
+    <path name="hifi-record usb-headset-mic">
+        <ctl name="MultiMedia2 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm845/sdm845.mk b/configs/sdm845/sdm845.mk
index 7d3a51f..e6f2b3d 100644
--- a/configs/sdm845/sdm845.mk
+++ b/configs/sdm845/sdm845.mk
@@ -7,6 +7,7 @@
 USE_CUSTOM_AUDIO_POLICY := 1
 AUDIO_FEATURE_ENABLED_COMPRESS_CAPTURE := false
 AUDIO_FEATURE_ENABLED_COMPRESS_VOIP := false
+AUDIO_FEATURE_ENABLED_DYNAMIC_ECNS := false
 AUDIO_FEATURE_ENABLED_EXTN_FORMATS := true
 AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER := true
 AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER := true
@@ -53,6 +54,7 @@
 AUDIO_FEATURE_ENABLED_SPKR_PROTECTION := true
 AUDIO_FEATURE_ENABLED_ACDB_LICENSE := false
 AUDIO_FEATURE_ENABLED_DEV_ARBI := false
+AUDIO_FEATURE_ENABLED_DYNAMIC_LOG := true
 MM_AUDIO_ENABLED_FTM := true
 TARGET_USES_QCOM_MM_AUDIO := true
 AUDIO_FEATURE_ENABLED_SOURCE_TRACKING := true
@@ -189,7 +191,7 @@
 
 #split a2dp DSP supported encoder list
 PRODUCT_PROPERTY_OVERRIDES += \
-persist.vendor.bt.a2dp_offload_cap=sbc-aptx-aptxhd-aac
+persist.vendor.bt.a2dp_offload_cap=sbc-aptx-aptxtws-aptxhd-aac
 
 #enable software decoders for ALAC and APE
 PRODUCT_PROPERTY_OVERRIDES += \
diff --git a/configs/sdm845/sound_trigger_platform_info.xml b/configs/sdm845/sound_trigger_platform_info.xml
index b9e36f5..e1f21a7 100644
--- a/configs/sdm845/sound_trigger_platform_info.xml
+++ b/configs/sdm845/sound_trigger_platform_info.xml
@@ -61,7 +61,7 @@
         <param library="libsmwrapper.so" />
         <param max_cpe_phrases="6" />
         <param max_cpe_users="3" />
-        <param max_ape_phrases="10" />
+        <param max_ape_phrases="20" />
         <param max_ape_users="10" />
         <!-- Profile specific data which the algorithm can support -->
         <param sample_rate="16000" />
diff --git a/hal/Android.mk b/hal/Android.mk
index d2ef726..cbf766a 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -368,6 +368,10 @@
     LOCAL_SRC_FILES += audio_extn/ip_hdlr_intf.c
 endif
 
+ifeq ($(strip $($AUDIO_FEATURE_ENABLED_DYNAMIC_ECNS)),true)
+    LOCAL_CFLAGS += -DDYNAMIC_ECNS_ENABLED
+endif
+
 LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_COPY_HEADERS_TO   := mm-audio
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 4393418..2c0c53b 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -100,6 +100,7 @@
     ENC_CODEC_TYPE_SBC = 520093696u, // 0x1F000000UL
     ENC_CODEC_TYPE_APTX = 536870912u, // 0x20000000UL
     ENC_CODEC_TYPE_APTX_HD = 553648128u, // 0x21000000UL
+    ENC_CODEC_TYPE_APTX_DUAL_MONO = 570425344u, // 0x22000000UL
     ENC_CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
 }enc_codec_t;
 
@@ -147,6 +148,7 @@
     int  a2dp_total_active_session_request;
     bool is_a2dp_offload_supported;
     bool is_handoff_in_progress;
+    bool is_aptx_dual_mono_supported;
 };
 
 struct a2dp_data a2dp;
@@ -169,7 +171,7 @@
     uint16_t      aac_fmt_flag;
     uint16_t      channel_cfg;
     uint32_t      sample_rate;
-} ;
+} __packed;
 
 /* SBC encoder configuration structure. */
 typedef struct sbc_enc_cfg_t sbc_enc_cfg_t;
@@ -189,14 +191,14 @@
     uint32_t      alloc_method;
     uint32_t      bit_rate;
     uint32_t      sample_rate;
-};
+} __packed;
 
 
 /* supported num_channels are Mono/Stereo
  * supported channel_mapping for mono is CHANNEL_C
  * supported channel mapping for stereo is CHANNEL_L and CHANNEL_R
  * custom size and reserved are not used(for future enhancement)
-  */
+ */
 struct custom_enc_cfg_t
 {
     uint32_t      enc_format;
@@ -205,7 +207,7 @@
     uint16_t      reserved;
     uint8_t       channel_mapping[8];
     uint32_t      custom_size;
-};
+} __packed;
 
 struct celt_specific_enc_cfg_t
 {
@@ -214,13 +216,31 @@
     uint16_t      complexity;
     uint16_t      prediction_mode;
     uint16_t      vbr_flag;
-};
+} __packed;
 
 struct celt_enc_cfg_t
 {
     struct custom_enc_cfg_t  custom_cfg;
     struct celt_specific_enc_cfg_t celt_cfg;
-};
+} __packed;
+
+/* sync_mode introduced with APTX V2 libraries
+ * sync mode: 0x0 = stereo sync mode
+ *            0x01 = dual mono sync mode
+ *            0x02 = dual mono with no sync on either L or R codewords
+ */
+struct aptx_v2_enc_cfg_ext_t
+{
+    uint32_t       sync_mode;
+} __packed;
+
+/* APTX struct for combining custom enc and V2 fields */
+struct aptx_enc_cfg_t
+{
+    struct custom_enc_cfg_t  custom_cfg;
+    struct aptx_v2_enc_cfg_ext_t aptx_v2_cfg;
+} __packed;
+
 /* In LE BT source code uses system/audio.h for below
  * structure definition. To avoid multiple definition
  * compilation error for audiohal in LE , masking structure
@@ -252,8 +272,19 @@
     uint16_t sampling_rate;
     uint8_t  channels;
     uint32_t bitrate;
-} audio_aptx_encoder_config;
+} audio_aptx_default_config;
 
+typedef struct {
+    uint16_t sampling_rate;
+    uint8_t  channels;
+    uint32_t bitrate;
+    uint32_t sync_mode;
+} audio_aptx_dual_mono_config;
+
+typedef union {
+    audio_aptx_default_config *default_cfg;
+    audio_aptx_dual_mono_config *dual_mono_cfg;
+} audio_aptx_encoder_config;
 
 /* Information about BT AAC encoder configuration
  * This data is used between audio HAL module and
@@ -299,6 +330,10 @@
             ALOGD("%s: aptx offload supported\n",__func__);
             a2dp.is_a2dp_offload_supported = true;
             break;
+        } else if (strcmp(tok, "aptxtws") == 0) {
+            ALOGD("%s: aptx dual mono offload supported\n",__func__);
+            a2dp.is_a2dp_offload_supported = true;
+            break;
         } else if (strcmp(tok, "aptxhd") == 0) {
             ALOGD("%s: aptx HD offload supported\n",__func__);
             a2dp.is_a2dp_offload_supported = true;
@@ -489,7 +524,7 @@
 bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
-    struct custom_enc_cfg_t aptx_dsp_cfg;
+    struct aptx_enc_cfg_t aptx_dsp_cfg;
     bool is_configured = false;
     int ret = 0;
 
@@ -502,22 +537,31 @@
         is_configured = false;
         goto fail;
     }
-    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_t));
-    aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX;
-    aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
-    aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
-    switch(aptx_dsp_cfg.num_channels) {
+
+    memset(&aptx_dsp_cfg, 0x0, sizeof(struct aptx_enc_cfg_t));
+    aptx_dsp_cfg.custom_cfg.enc_format = ENC_MEDIA_FMT_APTX;
+
+    if (!a2dp.is_aptx_dual_mono_supported) {
+        aptx_dsp_cfg.custom_cfg.sample_rate = aptx_bt_cfg->default_cfg->sampling_rate;
+        aptx_dsp_cfg.custom_cfg.num_channels = aptx_bt_cfg->default_cfg->channels;
+    } else {
+        aptx_dsp_cfg.custom_cfg.sample_rate = aptx_bt_cfg->dual_mono_cfg->sampling_rate;
+        aptx_dsp_cfg.custom_cfg.num_channels = aptx_bt_cfg->dual_mono_cfg->channels;
+        aptx_dsp_cfg.aptx_v2_cfg.sync_mode = aptx_bt_cfg->dual_mono_cfg->sync_mode;
+    }
+
+    switch(aptx_dsp_cfg.custom_cfg.num_channels) {
         case 1:
-            aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
+            aptx_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_C;
             break;
         case 2:
         default:
-            aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
-            aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
+            aptx_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+            aptx_dsp_cfg.custom_cfg.channel_mapping[1] = PCM_CHANNEL_R;
             break;
     }
     ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
-                              sizeof(struct custom_enc_cfg_t));
+                              sizeof(struct aptx_enc_cfg_t));
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX encoder config", __func__);
         is_configured = false;
@@ -539,16 +583,26 @@
     }
     is_configured = true;
     a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
-    a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
-    ALOGV("Successfully updated APTX enc format with samplingrate: %d channels:%d",
-           aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
+    if (!a2dp.is_aptx_dual_mono_supported) {
+        a2dp.enc_sampling_rate = aptx_bt_cfg->default_cfg->sampling_rate;
+        ALOGV("Successfully updated APTX enc format with samplingrate: %d \
+               channels:%d", aptx_dsp_cfg.custom_cfg.sample_rate,
+               aptx_dsp_cfg.custom_cfg.num_channels);
+    } else {
+        a2dp.enc_sampling_rate = aptx_bt_cfg->dual_mono_cfg->sampling_rate;
+        ALOGV("Successfully updated APTX dual mono enc format with \
+               samplingrate: %d channels:%d syncmode %d",
+               aptx_dsp_cfg.custom_cfg.sample_rate,
+               aptx_dsp_cfg.custom_cfg.num_channels,
+               aptx_dsp_cfg.aptx_v2_cfg.sync_mode);
+    }
 fail:
     return is_configured;
 }
 
 /* API to configure APTX HD DSP encoder
  */
-bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
+bool configure_aptx_hd_enc_format(audio_aptx_default_config *aptx_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
     struct custom_enc_cfg_t aptx_dsp_cfg;
@@ -743,6 +797,7 @@
     uint8_t multi_cast = 0, num_dev = 1;
     enc_codec_t codec_type = ENC_CODEC_TYPE_INVALID;
     bool is_configured = false;
+    audio_aptx_encoder_config aptx_encoder_cfg;
 
     if (!a2dp.audio_get_codec_config) {
         ALOGE(" a2dp handle is not identified, ignoring a2dp encoder config");
@@ -756,17 +811,26 @@
         case ENC_CODEC_TYPE_SBC:
             ALOGD(" Received SBC encoder supported BT device");
             is_configured =
-               configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
+              configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
             break;
         case ENC_CODEC_TYPE_APTX:
             ALOGD(" Received APTX encoder supported BT device");
+            a2dp.is_aptx_dual_mono_supported = false;
+            aptx_encoder_cfg.default_cfg = (audio_aptx_default_config *)codec_info;
             is_configured =
-              configure_aptx_enc_format((audio_aptx_encoder_config *)codec_info);
+              configure_aptx_enc_format(&aptx_encoder_cfg);
             break;
         case ENC_CODEC_TYPE_APTX_HD:
             ALOGD(" Received APTX HD encoder supported BT device");
             is_configured =
-             configure_aptx_hd_enc_format((audio_aptx_encoder_config *)codec_info);
+              configure_aptx_hd_enc_format((audio_aptx_default_config *)codec_info);
+            break;
+        case ENC_CODEC_TYPE_APTX_DUAL_MONO:
+            ALOGD(" Received APTX dual mono encoder supported BT device");
+            a2dp.is_aptx_dual_mono_supported = true;
+            aptx_encoder_cfg.dual_mono_cfg = (audio_aptx_dual_mono_config *)codec_info;
+            is_configured =
+              configure_aptx_enc_format(&aptx_encoder_cfg);
             break;
         case ENC_CODEC_TYPE_AAC:
             ALOGD(" Received AAC encoder supported BT device");
@@ -1044,6 +1108,7 @@
   a2dp.enc_sampling_rate = 48000;
   a2dp.is_a2dp_offload_supported = false;
   a2dp.is_handoff_in_progress = false;
+  a2dp.is_aptx_dual_mono_supported = false;
   reset_a2dp_enc_config_params();
   update_offload_codec_capabilities();
 }
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 4e5f4d8..7abc89b 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -240,11 +240,12 @@
     uint16_t num_output_channels;
     uint16_t num_input_channels;
     uint8_t has_output_channel_map;
-    uint32_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+    uint16_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
     uint8_t has_input_channel_map;
-    uint32_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+    uint16_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
     uint8_t has_mixer_coeffs;
-    float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
+    /* member for coefficient gains in Q14 format */
+    uint32_t mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
 } mix_matrix_params_t;
 
 typedef union {
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index c62226a..072d202 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -51,7 +51,7 @@
 #endif
 
 #ifndef INCALL_MUSIC_ENABLED
-#define AUDIO_OUTPUT_FLAG_INCALL_MUSIC 0x8000
+#define AUDIO_OUTPUT_FLAG_INCALL_MUSIC 0x80000000 //0x8000
 #endif
 
 #ifndef AUDIO_DEVICE_OUT_FM_TX
@@ -86,7 +86,7 @@
 #endif
 
 #ifndef AUDIO_FORMAT_AAC_LATM
-#define AUDIO_FORMAT_AAC_LATM 0x23000000UL
+#define AUDIO_FORMAT_AAC_LATM 0x80000000UL
 #define AUDIO_FORMAT_AAC_LATM_LC   (AUDIO_FORMAT_AAC_LATM |\
                                       AUDIO_FORMAT_AAC_SUB_LC)
 #define AUDIO_FORMAT_AAC_LATM_HE_V1 (AUDIO_FORMAT_AAC_LATM |\
@@ -116,7 +116,7 @@
 #endif
 
 #ifndef AUDIO_OUTPUT_FLAG_INTERACTIVE
-#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x80000000
+#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x4000000
 #endif
 
 #ifndef COMPRESS_METADATA_NEEDED
@@ -213,6 +213,9 @@
 #define audio_extn_usb_enable_sidetone(device, enable)                 (0)
 #define audio_extn_usb_set_sidetone_gain(parms, value, len)            (0)
 #define audio_extn_usb_is_capture_supported()                          (0)
+#define audio_extn_usb_get_max_channels(p)                             (0)
+#define audio_extn_usb_get_max_bit_width(p)                            (0)
+#define audio_extn_usb_get_sup_sample_rates(t, s, l)                   (0)
 #else
 void audio_extn_usb_init(void *adev);
 void audio_extn_usb_deinit();
@@ -226,6 +229,9 @@
 int audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
                                      char *value, int len);
 bool audio_extn_usb_is_capture_supported();
+int audio_extn_usb_get_max_channels(bool playback);
+int audio_extn_usb_get_max_bit_width(bool playback);
+int audio_extn_usb_get_sup_sample_rates(int type, uint32_t *sr, uint32_t l);
 #endif
 
 #ifndef SPLIT_A2DP_ENABLED
diff --git a/hal/audio_extn/keep_alive.c b/hal/audio_extn/keep_alive.c
index 3e9a91c..dad4946 100644
--- a/hal/audio_extn/keep_alive.c
+++ b/hal/audio_extn/keep_alive.c
@@ -124,7 +124,7 @@
 
     if (cmd == NULL) {
         ALOGE("%s: cmd is NULL", __func__);
-        return -ENOMEM;
+        return;
     }
 
     cmd->req = r;
diff --git a/hal/audio_extn/qaf.c b/hal/audio_extn/qaf.c
index ca83b1d..20d0ae4 100644
--- a/hal/audio_extn/qaf.c
+++ b/hal/audio_extn/qaf.c
@@ -129,6 +129,8 @@
 FILE *fp_output_writer_hdmi = NULL;
 #endif
 
+void set_hdmi_configuration_to_module();
+
 struct qaf_adsp_hdlr_config_state {
     struct audio_adsp_event event_params;
     /* For holding client audio_adsp_event payload */
@@ -386,7 +388,7 @@
 
 static int get_media_fmt_array_index_for_output_id(
         struct qaf_module* qaf_mod,
-        int output_id)
+        uint32_t output_id)
 {
     int i;
     for (i = 0; i < MAX_QAF_MODULE_OUT; i++) {
@@ -496,7 +498,7 @@
 {
     DEBUG_MSG();
 
-    int ret = 0, k;
+    int ret = 0;
     struct stream_out *out = p_qaf->passthrough_in;
 
     if (!out) return -EINVAL;
@@ -592,7 +594,7 @@
 static int audio_extn_qaf_stream_stop(struct stream_out *out)
 {
     int ret = 0;
-    DEBUG_MSG("Output Stream 0x%x", out);
+    DEBUG_MSG("Output Stream 0x%p", out);
 
     if (!check_stream_state(out, RUN)) return ret;
 
@@ -837,7 +839,7 @@
     return fragment_size;
 }
 
-static uint32_t qaf_get_pcm_offload_input_buffer_size(info)
+static uint32_t qaf_get_pcm_offload_input_buffer_size(audio_offload_info_t* info)
 {
     return qaf_get_pcm_offload_buffer_size(info, MS12_PCM_IN_FRAGMENT_SIZE);
 }
@@ -1132,21 +1134,22 @@
     DEBUG_MSG("Output Stream %p", out);
     lock_output_stream(out);
 
-    //If QAF passthrough is active then block the flush on module input streams.
-    if (p_qaf->passthrough_out) {
-        pthread_mutex_lock(&p_qaf->lock);
-        //If flush is received for the QAF passthrough stream then call the primary HAL api.
-        if (p_qaf->passthrough_in == out) {
-            status = p_qaf->passthrough_out->stream.flush(
-                    (struct audio_stream_out *)p_qaf->passthrough_out);
-            out->offload_state = OFFLOAD_STATE_IDLE;
+    if (!out->standby) {
+        //If QAF passthrough is active then block the flush on module input streams.
+        if (p_qaf->passthrough_out) {
+            pthread_mutex_lock(&p_qaf->lock);
+            //If flush is received for the QAF passthrough stream then call the primary HAL api.
+            if (p_qaf->passthrough_in == out) {
+                status = p_qaf->passthrough_out->stream.flush(
+                        (struct audio_stream_out *)p_qaf->passthrough_out);
+                out->offload_state = OFFLOAD_STATE_IDLE;
+            }
+            pthread_mutex_unlock(&p_qaf->lock);
+        } else {
+            //Flush the module input stream.
+            status = audio_extn_qaf_stream_flush(out);
         }
-        pthread_mutex_unlock(&p_qaf->lock);
-    } else {
-        //Flush the module input stream.
-        status = audio_extn_qaf_stream_flush(out);
     }
-
     unlock_output_stream(out);
     DEBUG_MSG("Exit");
     return status;
@@ -1227,7 +1230,7 @@
     if (media_fmt == NULL || out == NULL) {
         return;
     }
-    struct audio_out_channel_map_param chmap = {0};
+    struct audio_out_channel_map_param chmap = {0,{0}};
     int i = 0;
     chmap.channels = media_fmt->channels;
     for (i = 0; i < chmap.channels && i < AUDIO_CHANNEL_COUNT_MAX && i < AUDIO_QAF_MAX_CHANNELS;
@@ -1238,7 +1241,7 @@
 }
 
 /* Call back function for mm module. */
-static void notify_event_callback(audio_session_handle_t session_handle /*__unused*/,
+static void notify_event_callback(audio_session_handle_t session_handle __unused,
                                   void *prv_data,
                                   void *buf,
                                   audio_event_id_t event_id,
@@ -1255,7 +1258,7 @@
      1.Open compress device for HDMI(PCM or AC3) based on current hdmi o/p format and write
      data to the HDMI device.
      */
-    int ret, i;
+    int ret;
     audio_output_flags_t flags;
     struct qaf_module* qaf_mod = (struct qaf_module*)prv_data;
     struct audio_stream_out *bt_stream = NULL;
@@ -1293,7 +1296,7 @@
         audio_qaf_out_buffer_t *buf_payload = (audio_qaf_out_buffer_t*)buf;
         int index = -1;
 
-        if (size < sizeof(audio_qaf_out_buffer_t)) {
+        if ((uint32_t)size < sizeof(audio_qaf_out_buffer_t)) {
             ERROR_MSG("AUDIO_DATA_EVENT_V2 payload size is not sufficient.");
             return;
         }
@@ -1338,7 +1341,7 @@
         audio_qaf_media_format_t *p_cached_fmt = NULL;
         int index = -1;
 
-        if (size < sizeof(audio_qaf_media_format_t)) {
+        if ( (uint32_t)size < sizeof(audio_qaf_media_format_t)) {
             ERROR_MSG("Size is not proper for the event AUDIO_OUTPUT_MEDIA_FORMAT_EVENT.");
             return ;
         }
@@ -1448,7 +1451,6 @@
             /* CASE 2: Multi-Channel PCM output to HDMI.
              * If any other HDMI output is already enabled then this has to be dropped.
              */
-            bool create_mch_out_stream = false;
 
             if (p_qaf->passthrough_enabled) {
                 //Closing all the multi-Channel PCM HDMI output stream from QAF.
@@ -1487,7 +1489,7 @@
                 }
 
                 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                flags = (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_DIRECT_PCM);
+                flags = AUDIO_OUTPUT_FLAG_DIRECT;
 
                 ret = adev_open_output_stream((struct audio_hw_device *)p_qaf->adev,
                                               QAF_DEFAULT_COMPR_AUDIO_HANDLE,
@@ -1603,7 +1605,7 @@
                     devices = device;
                 }
 
-                flags = (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_DIRECT_PCM);
+                flags = AUDIO_OUTPUT_FLAG_DIRECT;
 
                 /* TODO:: Need to Propagate errors to framework */
                 ret = adev_open_output_stream((struct audio_hw_device *)p_qaf->adev,
@@ -1855,7 +1857,7 @@
 {
     ALOGV("%s %d", __func__, __LINE__);
     unsigned char* license_data = NULL;
-    device_license_config_t lic_config = {0};
+    device_license_config_t lic_config = {NULL, 0, 0};
     int ret = -ENOSYS, size = 0;
     char value[PROPERTY_VALUE_MAX] = {0};
     struct qaf_module *qaf_mod = NULL;
@@ -2264,9 +2266,8 @@
 /* Sets the stream set parameters (device routing information). */
 static int qaf_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
 {
-    struct str_parms *parms, *new_parms;
+    struct str_parms *parms;
     char value[32];
-    char *new_kv_pairs;
     int val = 0;
     struct stream_out *out = (struct stream_out *)stream;
     int ret = 0;
@@ -2410,7 +2411,7 @@
 
         /*ADSP event is not supported for passthrough*/
         if ((param_id == AUDIO_EXTN_PARAM_ADSP_STREAM_CMD)
-            && !(new_out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) continue;
+            && !(new_out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) continue;
         if (new_out->standby)
             new_out->stream.write((struct audio_stream_out *)new_out, NULL, 0);
         lock_output_stream(new_out);
@@ -2427,8 +2428,7 @@
                              audio_extn_param_payload *payload)
 {
     int ret = -EINVAL, i;
-    struct stream_out *new_out;
-    struct audio_usecase *uc_info;
+    struct stream_out *new_out = NULL;
     struct qaf_module *qaf_mod = get_qaf_module_for_input_stream(out);
 
     if (!out || !qaf_mod || !payload) {
@@ -2521,7 +2521,7 @@
         out->config.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT;
         out->config.start_threshold = QAF_DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
         out->config.avail_min = QAF_DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
-    } else if(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
+    } else if(out->flags == AUDIO_OUTPUT_FLAG_DIRECT) {
         out->compr_config.fragment_size = qaf_get_pcm_offload_input_buffer_size(&(config->offload_info));
     }
 
@@ -2541,7 +2541,12 @@
     struct stream_out *out = (struct stream_out *)stream;
     struct qaf_module* qaf_mod = get_qaf_module_for_input_stream(out);
 
-    if (!qaf_mod) return;
+    if (!qaf_mod) {
+        DEBUG_MSG("qaf module is NULL, by passing qaf on close output stream");
+        /*closing non-MS12/default output stream opened with qaf */
+        adev_close_output_stream(dev, stream);
+        return;
+    }
 
     DEBUG_MSG("stream_handle(%p) format = %x", out, out->format);
 
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 7b0309b..60216b1 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -53,10 +53,14 @@
 #define SAMPLE_RATE_11025         11025
 // Supported sample rates for USB
 static uint32_t supported_sample_rates[] =
-    {8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000};
+    {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
+static uint32_t supported_sample_rates_mask[2];
 
 #define  MAX_SAMPLE_RATE_SIZE  sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
 
+#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
+#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
+
 enum usb_usecase_type{
     USB_PLAYBACK = 0,
     USB_CAPTURE,
@@ -246,7 +250,7 @@
     return 0;
 }
 
-static int usb_get_sample_rates(char *rates_str,
+static int usb_get_sample_rates(int type, char *rates_str,
                                 struct usb_device_config *config)
 {
     uint32_t i;
@@ -277,6 +281,7 @@
             if (supported_sample_rates[i] >= min_sr &&
                 supported_sample_rates[i] <= max_sr) {
                 config->rates[sr_size++] = supported_sample_rates[i];
+                supported_sample_rates_mask[type] |= (1<<i);
                 ALOGI_IF(usb_audio_debug_enable,
                     "%s: continuous sample rate supported_sample_rates[%d] %d",
                     __func__, i, supported_sample_rates[i]);
@@ -291,6 +296,7 @@
                         "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
                         __func__, sr, i, supported_sample_rates[i]);
                     config->rates[sr_size++] = supported_sample_rates[i];
+                    supported_sample_rates_mask[type] |= (1<<i);
                 }
             }
             next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
@@ -455,7 +461,7 @@
         }
         memcpy(rates_str, rates_str_start, size);
         rates_str[size] = '\0';
-        ret = usb_get_sample_rates(rates_str, usb_device_info);
+        ret = usb_get_sample_rates(type, rates_str, usb_device_info);
         if (rates_str)
             free(rates_str);
         if (ret < 0) {
@@ -551,13 +557,24 @@
     return;
 }
 
-static bool usb_valid_device(int device)
+static inline bool usb_output_device(audio_devices_t device) {
+    // ignore accessory for now
+    if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
+        return false;
+    return audio_is_usb_out_device(device);
+}
+
+static inline bool usb_input_device(audio_devices_t device) {
+    // ignore accessory for now
+    if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
+        return false;
+    return audio_is_usb_in_device(device);
+}
+
+static bool usb_valid_device(audio_devices_t device)
 {
-    bool is_usb_device = false;
-    if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
-        (device & AUDIO_DEVICE_IN_USB_DEVICE))
-        is_usb_device = true;
-    return is_usb_device;
+    return usb_output_device(device) ||
+           usb_input_device(device);
 }
 
 static void usb_print_active_device(void){
@@ -852,7 +869,7 @@
         card_info = node_to_item(node_i, struct usb_card_config, list);
         ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
                __func__,  card_info->usb_device_type, card_info->usb_card);
-        if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+        if (usb_output_device(card_info->usb_device_type)) {
             if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
                 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
                                 card_info->usb_snd_mixer,
@@ -898,8 +915,8 @@
                  "%s: card_dev_type (0x%x), card_no(%d)",
                  __func__,  card_info->usb_device_type, card_info->usb_card);
         /* Currently only apply the first playback sound card configuration */
-        if ((is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) ||
-            ((!is_playback) && card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE)){
+        if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
+            (!is_playback && usb_input_device(card_info->usb_device_type))){
             is_usb_supported = usb_audio_backend_apply_policy(
                                            &card_info->usb_device_conf_list,
                                            bit_width,
@@ -914,6 +931,70 @@
     return is_usb_supported;
 }
 
+int audio_extn_usb_get_max_channels(bool is_playback)
+{
+    struct listnode *node_i, *node_j;
+    struct usb_device_config *dev_info;
+    struct usb_card_config *card_info;
+    unsigned int max_ch = 1;
+    list_for_each(node_i, &usbmod->usb_card_conf_list) {
+            card_info = node_to_item(node_i, struct usb_card_config, list);
+            if (usb_output_device(card_info->usb_device_type) && !is_playback)
+                continue;
+            else if (usb_input_device(card_info->usb_device_type) && is_playback)
+                continue;
+
+            list_for_each(node_j, &card_info->usb_device_conf_list) {
+                dev_info = node_to_item(node_j, struct usb_device_config, list);
+                max_ch = _MAX(max_ch, dev_info->channels);
+            }
+    }
+
+    return max_ch;
+}
+
+int audio_extn_usb_get_max_bit_width(bool is_playback)
+{
+    struct listnode *node_i, *node_j;
+    struct usb_device_config *dev_info;
+    struct usb_card_config *card_info;
+    unsigned int max_bw = 16;
+    list_for_each(node_i, &usbmod->usb_card_conf_list) {
+            card_info = node_to_item(node_i, struct usb_card_config, list);
+            if (usb_output_device(card_info->usb_device_type) && !is_playback)
+                continue;
+            else if (usb_input_device(card_info->usb_device_type) && is_playback)
+                continue;
+
+            list_for_each(node_j, &card_info->usb_device_conf_list) {
+                dev_info = node_to_item(node_j, struct usb_device_config, list);
+                max_bw = _MAX(max_bw, dev_info->bit_width);
+            }
+    }
+
+    return max_bw;
+}
+
+int audio_extn_usb_get_sup_sample_rates(bool is_playback,
+                                        uint32_t *sample_rates,
+                                        uint32_t sample_rate_size)
+{
+    int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
+
+    ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
+    uint32_t bm = supported_sample_rates_mask[type];
+    uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
+
+    int i = 0;
+    while (tries--) {
+        int idx = __builtin_ffs(bm) - 1;
+        sample_rates[i++] = supported_sample_rates[idx];
+        bm &= ~(1<<idx);
+    }
+
+    return i;
+}
+
 bool audio_extn_usb_is_capture_supported()
 {
     if (usbmod == NULL) {
@@ -968,18 +1049,18 @@
         goto exit;
     }
     list_init(&usb_card_info->usb_device_conf_list);
-    if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+    if (usb_output_device(device)) {
         if (!usb_get_device_pb_config(usb_card_info, card)){
             usb_card_info->usb_card = card;
-            usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
+            usb_card_info->usb_device_type = device;
             usb_get_sidetone_mixer(usb_card_info);
             list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
             goto exit;
         }
-    } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
+    } else if (usb_input_device(device)) {
         if (!usb_get_device_cap_config(usb_card_info, card)) {
             usb_card_info->usb_card = card;
-            usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
+            usb_card_info->usb_device_type = device;
             usbmod->is_capture_supported = true;
             list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
             goto exit;
@@ -1034,7 +1115,12 @@
             free(node_to_item(node_i, struct usb_card_config, list));
         }
     }
-    usbmod->is_capture_supported = false;
+    if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
+        usbmod->is_capture_supported = false;
+        supported_sample_rates_mask[USB_CAPTURE] = 0;
+    } else
+        supported_sample_rates_mask[USB_PLAYBACK] = 0;
+
 exit:
     if (usb_audio_debug_enable)
         usb_print_active_device();
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index c01e6f7..9f99a94 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -955,7 +955,9 @@
                sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         }
 
-        if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+        if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
+            usecase->stream.out->app_type_cfg.sample_rate = usecase->stream.out->sample_rate;
+        } else if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
             usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
         } else if ((snd_device == SND_DEVICE_OUT_HDMI ||
                     snd_device == SND_DEVICE_OUT_USB_HEADSET ||
@@ -1016,6 +1018,8 @@
         app_type = usecase->stream.in->app_type_cfg.app_type;
         app_type_cfg[len++] = app_type;
         app_type_cfg[len++] = acdb_dev_id;
+        if (usecase->id == USECASE_AUDIO_RECORD_VOIP)
+            usecase->stream.in->app_type_cfg.sample_rate = usecase->stream.in->sample_rate;
         sample_rate = usecase->stream.in->app_type_cfg.sample_rate;
         app_type_cfg[len++] = sample_rate;
         if (snd_device_be_idx > 0)
@@ -1246,8 +1250,7 @@
      *be multiple of (number of channels * bytes per sample)
      *For writes to succeed, the buffer must be written at address which is multiple of 32
      */
-    fragment_size = ALIGN(fragment_size, (bytes_per_sample * noOfChannels));
-    fragment_size = ALIGN(fragment_size, 32);
+    fragment_size = ALIGN(fragment_size, (bytes_per_sample * noOfChannels * 32));
 
     ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
     return fragment_size;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1699340..be65139 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -63,6 +63,7 @@
 #include <cutils/sched_policy.h>
 
 #include <hardware/audio_effect.h>
+#include <hardware/audio_alsaops.h>
 #include <system/thread_defs.h>
 #include <tinyalsa/asoundlib.h>
 #include <audio_effects/effect_aec.h>
@@ -116,6 +117,10 @@
     .format = PCM_FORMAT_S16_LE,
 };
 
+#define MIN_CHANNEL_COUNT                1
+#define DEFAULT_CHANNEL_COUNT            2
+#define MAX_HIFI_CHANNEL_COUNT           8
+
 static unsigned int configured_low_latency_capture_period_size =
         LOW_LATENCY_CAPTURE_PERIOD_SIZE;
 
@@ -184,6 +189,17 @@
     .avail_min = MMAP_PERIOD_SIZE, //1 ms
 };
 
+struct pcm_config pcm_config_hifi = {
+    .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
+    .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
+    .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
+    .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
+    .format = PCM_FORMAT_S24_3LE,
+    .start_threshold = 0,
+    .stop_threshold = INT_MAX,
+    .avail_min = 0,
+};
+
 struct pcm_config pcm_config_audio_capture = {
     .channels = 2,
     .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
@@ -276,6 +292,7 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
     [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
     [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
+    [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
 
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
@@ -285,6 +302,7 @@
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
     [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
     [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
+    [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
 
     [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
     [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
@@ -361,7 +379,7 @@
     uint32_t value;
 };
 
-static const struct string_to_enum out_channels_name_to_enum_table[] = {
+static const struct string_to_enum channels_name_to_enum_table[] = {
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
@@ -370,9 +388,23 @@
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+    STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
+    STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
 };
 
-static const struct string_to_enum out_formats_name_to_enum_table[] = {
+static const struct string_to_enum formats_name_to_enum_table[] = {
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
     STRING_TO_ENUM(AUDIO_FORMAT_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
@@ -387,7 +419,7 @@
     32000, 44100, 48000, 88200, 96000, 176400, 192000,
 };
 
-static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
+static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
     STRING_TO_ENUM(32000),
     STRING_TO_ENUM(44100),
     STRING_TO_ENUM(48000),
@@ -524,6 +556,17 @@
     return 0;
 }
 
+static inline void adjust_frames_for_device_delay(struct stream_out *out,
+                                                  uint32_t *dsp_frames) {
+    // Adjustment accounts for A2dp encoder latency with offload usecases
+    // Note: Encoder latency is returned in ms.
+    if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
+        unsigned long offset =
+                (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
+        *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
+    }
+}
+
 __attribute__ ((visibility ("default")))
 bool audio_hw_send_gain_dep_calibration(int level) {
     bool ret_val = false;
@@ -771,6 +814,126 @@
     }
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
+                          struct audio_effect_config effect_config,
+                          unsigned int param_value)
+{
+    char mixer_ctl_name[] = "Audio Effect";
+    struct mixer_ctl *ctl;
+    long set_values[6];
+    struct stream_in *in = adev->active_input;
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get mixer ctl - %s",
+               __func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+
+    set_values[0] = 1; //0:Rx 1:Tx
+    set_values[1] = in->app_type_cfg.app_type;
+    set_values[2] = (long)effect_config.module_id;
+    set_values[3] = (long)effect_config.instance_id;
+    set_values[4] = (long)effect_config.param_id;
+    set_values[5] = param_value;
+
+    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+    return 0;
+
+}
+
+static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
+                               int effect_type, unsigned int *param_value)
+{
+    int ret = 0;
+    struct audio_effect_config other_effect_config;
+    struct audio_usecase *usecase = NULL;
+    struct stream_in *in = adev->active_input;
+
+    usecase = get_usecase_from_list(adev, in->usecase);
+    if (!usecase)
+        return -EINVAL;
+
+    ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
+                                            effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
+    if (ret < 0) {
+        ALOGE("%s Failed to get effect params %d", __func__, ret);
+        return ret;
+    }
+
+    if (module_id == other_effect_config.module_id) {
+            //Same module id for AEC/NS. Values need to be combined
+            if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
+                ((effect_type == EFFECT_NS) && (in->enable_aec))) {
+                *param_value |= other_effect_config.param_value;
+            }
+    }
+
+    return ret;
+}
+
+static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
+{
+    struct audio_effect_config effect_config;
+    struct audio_usecase *usecase = NULL;
+    int ret = 0;
+    unsigned int param_value = 0;
+    struct stream_in *in = adev->active_input;
+
+    if (!in) {
+        ALOGE("%s: Invalid input stream", __func__);
+        return -EINVAL;
+    }
+
+    ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
+
+    usecase = get_usecase_from_list(adev, in->usecase);
+
+    ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
+    if (ret < 0) {
+        ALOGE("%s Failed to get module id %d", __func__, ret);
+        return ret;
+    }
+    ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
+           in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
+
+    if(enable)
+        param_value = effect_config.param_value;
+
+    /*Special handling for AEC & NS effects Param values need to be
+      updated if module ids are same*/
+
+    if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
+        ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
+        if (ret < 0)
+            return ret;
+    }
+
+    ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
+
+    return ret;
+}
+
+static void check_and_enable_effect(struct audio_device *adev)
+{
+
+    if (adev->active_input->enable_aec) {
+        enable_disable_effect(adev, EFFECT_AEC, true);
+    }
+
+    if (adev->active_input->enable_ns &&
+        adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+        enable_disable_effect(adev, EFFECT_NS, true);
+    }
+}
+#else
+#define enable_disable_effect(x, y, z) ENOSYS
+#define check_and_enable_effect(x) ENOSYS
+#endif
+
+
 int pcm_ioctl(struct pcm *pcm, int request, ...)
 {
     va_list ap;
@@ -971,6 +1134,10 @@
         if (platform_can_enable_spkr_prot_on_device(snd_device) &&
              audio_extn_spkr_prot_is_enabled()) {
             audio_extn_spkr_prot_stop_processing(snd_device);
+
+            // when speaker device is disabled, reset swap.
+            // will be renabled on usecase start
+            platform_set_swap_channels(adev, false);
         } else if (platform_split_snd_device(adev->platform,
                                              snd_device,
                                              &num_devices,
@@ -1444,6 +1611,118 @@
     return ret;
 }
 
+static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
+                                         uint32_t *supported_sample_rates __unused,
+                                         uint32_t max_rates __unused)
+{
+    ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
+                                                        supported_sample_rates,
+                                                        max_rates);
+    ssize_t i = 0;
+
+    for (i=0; i<count; i++) {
+        ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
+              supported_sample_rates[i]);
+    }
+    return count;
+}
+
+static inline int read_usb_sup_channel_masks(bool is_playback,
+                                      audio_channel_mask_t *supported_channel_masks,
+                                      uint32_t max_masks)
+{
+    int channels = audio_extn_usb_get_max_channels(is_playback);
+    int channel_count;
+    uint32_t num_masks = 0;
+    if (channels > MAX_HIFI_CHANNEL_COUNT)
+        channels = MAX_HIFI_CHANNEL_COUNT;
+
+    if (is_playback) {
+        // For playback we never report mono because the framework always outputs stereo
+        channel_count = DEFAULT_CHANNEL_COUNT;
+        // audio_channel_out_mask_from_count() does return positional masks for channel counts
+        // above 2 but we want indexed masks here. So we
+        for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
+            supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
+        }
+        for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
+            supported_channel_masks[num_masks++] =
+                    audio_channel_mask_for_index_assignment_from_count(channel_count);
+        }
+    } else {
+        // For capture we report all supported channel masks from 1 channel up.
+        channel_count = MIN_CHANNEL_COUNT;
+        // audio_channel_in_mask_from_count() does the right conversion to either positional or
+        // indexed mask
+        for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
+            supported_channel_masks[num_masks++] =
+                    audio_channel_in_mask_from_count(channel_count);
+        }
+    }
+    ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
+          is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
+    return num_masks;
+}
+
+static inline int read_usb_sup_formats(bool is_playback __unused,
+                                audio_format_t *supported_formats,
+                                uint32_t max_formats __unused)
+{
+    int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
+    switch (bitwidth) {
+        case 24:
+            // XXX : usb.c returns 24 for s24 and s24_le?
+            supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+            break;
+        case 32:
+            supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
+            break;
+        case 16:
+        default :
+            supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
+            break;
+    }
+    ALOGV("%s: %s supported format %d", __func__,
+          is_playback ? "P" : "C", bitwidth);
+    return 1;
+}
+
+static inline int read_usb_sup_params_and_compare(bool is_playback,
+                                           audio_format_t *format,
+                                           audio_format_t *supported_formats,
+                                           uint32_t max_formats,
+                                           audio_channel_mask_t *mask,
+                                           audio_channel_mask_t *supported_channel_masks,
+                                           uint32_t max_masks,
+                                           uint32_t *rate,
+                                           uint32_t *supported_sample_rates,
+                                           uint32_t max_rates) {
+    int ret = 0;
+    int num_formats;
+    int num_masks;
+    int num_rates;
+    int i;
+
+    num_formats = read_usb_sup_formats(is_playback, supported_formats,
+                                       max_formats);
+    num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
+                                           max_masks);
+
+    num_rates = read_usb_sup_sample_rates(is_playback,
+                                          supported_sample_rates, max_rates);
+
+#define LUT(table, len, what, dflt)                  \
+    for (i=0; i<len && (table[i] != what); i++);    \
+    if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
+
+    LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
+    LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
+    LUT(supported_sample_rates, num_rates, *rate, 0);
+
+#undef LUT
+    return ret < 0 ? -EINVAL : 0; // HACK TBD
+}
+
 audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
                                                  usecase_type_t type)
 {
@@ -1634,8 +1913,12 @@
     bool ret = false;
     bool is_it_true_mode = false;
 
+    if(usecase->stream.out == NULL) {
+        ALOGE("%s: stream.out is NULL", __func__);
+        return false;
+    }
+
     if (is_offload_usecase(usecase->id) &&
-        (usecase->stream.out) &&
         (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
         (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
          usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
@@ -1650,8 +1933,7 @@
     // Force all a2dp output devices to reconfigure for proper AFE encode format
     //Also handle a case where in earlier a2dp start failed as A2DP stream was
     //in suspended state, hence try to trigger a retry when we again get a routing request.
-    if((usecase->stream.out) &&
-       (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
+    if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
         audio_extn_a2dp_is_force_device_switch()) {
          ALOGD("Force a2dp device switch to update new encoder config");
          ret = true;
@@ -1968,6 +2250,11 @@
     }
     enable_audio_route(adev, usecase);
 
+    /* If input stream is already running then effect needs to be
+       applied on the new input device that's being enabled here.  */
+    if ((in_snd_device != SND_DEVICE_NONE) && (!adev->active_input->standby))
+        check_and_enable_effect(adev);
+
     if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
         /* Enable aanc only if voice call exists */
         if (voice_is_call_state_active(adev))
@@ -2162,8 +2449,10 @@
               __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
 
         while (1) {
+            ATRACE_BEGIN("pcm_in_open");
             in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
                                flags, &config);
+            ATRACE_END();
             if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
                 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
                 if (in->pcm != NULL) {
@@ -2181,7 +2470,9 @@
         }
 
         ALOGV("%s: pcm_prepare", __func__);
+        ATRACE_BEGIN("pcm_in_prepare");
         ret = pcm_prepare(in->pcm);
+        ATRACE_END();
         if (ret < 0) {
             ALOGE("%s: pcm_prepare returned %d", __func__, ret);
             pcm_close(in->pcm);
@@ -2190,7 +2481,9 @@
         }
         register_in_stream(in);
         if (in->realtime) {
+            ATRACE_BEGIN("pcm_in_start");
             ret = pcm_start(in->pcm);
+            ATRACE_END();
             if (ret < 0) {
                 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
                 pcm_close(in->pcm);
@@ -2200,6 +2493,8 @@
         }
     }
 
+    check_and_enable_effect(adev);
+
 done_open:
     audio_extn_perf_lock_release(&adev->perf_lock_handle);
     ALOGD("%s: exit", __func__);
@@ -2584,6 +2879,7 @@
     char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
     bool a2dp_combo = false;
 
+    ATRACE_BEGIN("start_output_stream");
     if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
         ret = -EINVAL;
         goto error_config;
@@ -2723,8 +3019,10 @@
         }
 
         while (1) {
+            ATRACE_BEGIN("pcm_open");
             out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
                                flags, &out->config);
+            ATRACE_END();
             if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
                 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
                 if (out->pcm != NULL) {
@@ -2743,7 +3041,9 @@
 
         ALOGV("%s: pcm_prepare", __func__);
         if (pcm_is_ready(out->pcm)) {
+            ATRACE_BEGIN("pcm_prepare");
             ret = pcm_prepare(out->pcm);
+            ATRACE_END();
             if (ret < 0) {
                 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
                 pcm_close(out->pcm);
@@ -2763,9 +3063,11 @@
                                                 adev->dsp_bit_width_enforce_mode,
                                                 true);
         out->pcm = NULL;
+        ATRACE_BEGIN("compress_open");
         out->compr = compress_open(adev->snd_card,
                                    out->pcm_device_id,
                                    COMPRESS_IN, &out->compr_config);
+        ATRACE_END();
         if (out->compr && !is_compress_ready(out->compr)) {
             ALOGE("%s: %s", __func__, compress_get_error(out->compr));
             compress_close(out->compr);
@@ -2816,7 +3118,9 @@
                 ALOGE("%s: pcm stream not ready", __func__);
                 goto error_open;
             }
+            ATRACE_BEGIN("pcm_start");
             ret = pcm_start(out->pcm);
+            ATRACE_END();
             if (ret < 0)
                 goto error_open;
         }
@@ -2831,6 +3135,14 @@
             ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
     }
 
+    // consider a scenario where on pause lower layers are tear down.
+    // so on resume, swap mixer control need to be sent only when
+    // backend is active, hence rather than sending from enable device
+    // sending it from start of streamtream
+
+    platform_set_swap_channels(adev, true);
+
+    ATRACE_END();
     return ret;
 error_open:
     audio_extn_perf_lock_release(&adev->perf_lock_handle);
@@ -2841,6 +3153,7 @@
      * drivers to recover incases like SSR.
      */
     usleep(50000);
+    ATRACE_END();
     return ret;
 }
 
@@ -2854,7 +3167,8 @@
         (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
         (format != AUDIO_FORMAT_PCM_FLOAT)) &&
         !voice_extn_compress_voip_is_format_supported(format) &&
-        !audio_extn_compr_cap_format_supported(format))  ret = -EINVAL;
+        !audio_extn_compr_cap_format_supported(format))
+            ret = -EINVAL;
 
     switch (channel_count) {
     case 1:
@@ -3129,6 +3443,7 @@
           stream, out->usecase, use_case_table[out->usecase]);
 
     if (!out->standby) {
+        ATRACE_BEGIN("out_standby_l");
         if (adev->adm_deregister_stream)
             adev->adm_deregister_stream(adev->adm_data, out->handle);
 
@@ -3140,6 +3455,7 @@
             voice_extn_compress_voip_close_output_stream(stream);
             out->started = 0;
             ALOGD("VOIP output entered standby");
+            ATRACE_END();
             return 0;
         } else if (!is_offload_usecase(out->usecase)) {
             if (out->pcm) {
@@ -3158,6 +3474,7 @@
             }
         }
         stop_output_stream(out);
+        ATRACE_END();
     }
     ALOGD("%s: exit", __func__);
     return 0;
@@ -3356,8 +3673,13 @@
                     select_devices(adev, out->usecase);
                     out->devices = new_dev;
                 }
-                if (!same_dev)
+
+                if (!same_dev) {
+                    // on device switch force swap, lower functions will make sure
+                    // to check if swap is allowed or not.
+                    platform_set_swap_channels(adev, true);
                     audio_extn_perf_lock_release(&adev->perf_lock_handle);
+                }
                 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
                     out->a2dp_compress_mute &&
                     (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
@@ -3442,6 +3764,103 @@
     return ret;
 }
 
+static bool stream_get_parameter_channels(struct str_parms *query,
+                                          struct str_parms *reply,
+                                          audio_channel_mask_t *supported_channel_masks) {
+    int ret = -1;
+    char value[512];
+    bool first = true;
+    size_t i, j;
+
+    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
+        ret = 0;
+        value[0] = '\0';
+        i = 0;
+        while (supported_channel_masks[i] != 0) {
+            for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
+                if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
+                    if (!first)
+                        strlcat(value, "|", sizeof(value));
+
+                    strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
+                    first = false;
+                    break;
+                }
+            }
+            i++;
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
+    }
+    return ret == 0;
+}
+
+static bool stream_get_parameter_formats(struct str_parms *query,
+                                         struct str_parms *reply,
+                                         audio_format_t *supported_formats) {
+    int ret = -1;
+    char value[256];
+    size_t i, j;
+    bool first = true;
+
+    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
+        ret = 0;
+        value[0] = '\0';
+        i = 0;
+        while (supported_formats[i] != 0) {
+            for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
+                if (formats_name_to_enum_table[j].value == supported_formats[i]) {
+                    if (!first) {
+                        strlcat(value, "|", sizeof(value));
+                    }
+                    strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
+                    first = false;
+                    break;
+                }
+            }
+            i++;
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
+    }
+    return ret == 0;
+}
+
+static bool stream_get_parameter_rates(struct str_parms *query,
+                                       struct str_parms *reply,
+                                       uint32_t *supported_sample_rates) {
+
+    int i;
+    char value[256];
+    int ret = -1;
+    if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
+        ret = 0;
+        value[0] = '\0';
+        i=0;
+        int cursor = 0;
+        while (supported_sample_rates[i]) {
+            int avail = sizeof(value) - cursor;
+            ret = snprintf(value + cursor, avail, "%s%d",
+                           cursor > 0 ? "|" : "",
+                           supported_sample_rates[i]);
+            if (ret < 0 || ret >= avail) {
+                // if cursor is at the last element of the array
+                //    overwrite with \0 is duplicate work as
+                //    snprintf already put a \0 in place.
+                // else
+                //    we had space to write the '|' at value[cursor]
+                //    (which will be overwritten) or no space to fill
+                //    the first element (=> cursor == 0)
+                value[cursor] = '\0';
+                break;
+            }
+            cursor += ret;
+            ++i;
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
+                          value);
+    }
+    return ret >= 0;
+}
+
 static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
 {
     struct stream_out *out = (struct stream_out *)stream;
@@ -3464,18 +3883,18 @@
         return NULL;
     }
 
-    ALOGV("%s: enter: keys - %s", __func__, keys);
+    ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
     ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
     if (ret >= 0) {
         value[0] = '\0';
         i = 0;
         while (out->supported_channel_masks[i] != 0) {
-            for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
-                if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
+            for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
+                if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
                     if (!first) {
                         strlcat(value, "|", sizeof(value));
                     }
-                    strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
+                    strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
                     first = false;
                     break;
                 }
@@ -3513,12 +3932,12 @@
         i = 0;
         first = true;
         while (out->supported_formats[i] != 0) {
-            for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
-                if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
+            for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
+                if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
                     if (!first) {
                         strlcat(value, "|", sizeof(value));
                     }
-                    strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
+                    strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
                     first = false;
                     break;
                 }
@@ -3537,12 +3956,12 @@
         i = 0;
         first = true;
         while (out->supported_sample_rates[i] != 0) {
-            for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
-                if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
+            for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
+                if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
                     if (!first) {
                         strlcat(value, "|", sizeof(value));
                     }
-                    strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
+                    strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
                     first = false;
                     break;
                 }
@@ -3743,6 +4162,7 @@
     ssize_t ret = 0;
     int channels = 0;
 
+    ATRACE_BEGIN("out_write");
     lock_output_stream(out);
 
     if (CARD_STATUS_OFFLINE == out->card_status) {
@@ -3751,6 +4171,7 @@
             /*during SSR for compress usecase we should return error to flinger*/
             ALOGD(" copl %s: sound card is not active/SSR state", __func__);
             pthread_mutex_unlock(&out->lock);
+            ATRACE_END();
             return -ENETRESET;
         } else {
             ALOGD(" %s: sound card is not active/SSR state", __func__);
@@ -3879,6 +4300,7 @@
                 ALOGW("Error written bytes %zu > %d (fragment_size)",
                        bytes, out->hal_fragment_size);
                 pthread_mutex_unlock(&out->lock);
+                ATRACE_END();
                 return -EINVAL;
             } else {
                 audio_format_t dst_format = out->hal_op_format;
@@ -3919,6 +4341,7 @@
             out->card_status = CARD_STATUS_OFFLINE;
             pthread_mutex_unlock(&out->lock);
             out_on_error(&out->stream.common);
+            ATRACE_END();
             return ret;
         }
 
@@ -3939,6 +4362,7 @@
                                                      out->playback_started);
         }
         pthread_mutex_unlock(&out->lock);
+        ATRACE_END();
         return ret;
     } else {
         if (out->pcm) {
@@ -4028,9 +4452,11 @@
 
         if (audio_extn_passthru_is_passthrough_stream(out)) {
                 ALOGE("%s: write error, ret = %ld", __func__, ret);
+                ATRACE_END();
                 return ret;
         }
     }
+    ATRACE_END();
     return bytes;
 }
 
@@ -4052,6 +4478,7 @@
         if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
             *dsp_frames = get_actual_pcm_frames_rendered(out);
              ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
+             adjust_frames_for_device_delay(out, dsp_frames);
              return 0;
         }
 
@@ -4080,11 +4507,13 @@
             ret = -EINVAL;
         } else {
             ret = 0;
+            adjust_frames_for_device_delay(out, dsp_frames);
         }
         pthread_mutex_unlock(&out->lock);
         return ret;
     } else if (audio_is_linear_pcm(out->format)) {
         *dsp_frames = out->written;
+        adjust_frames_for_device_delay(out, dsp_frames);
         return 0;
     } else
         return -EINVAL;
@@ -4364,8 +4793,8 @@
     struct stream_out *out = (struct stream_out *)stream;
     struct audio_device *adev = out->dev;
     int ret = 0;
-    unsigned int offset1;
-    unsigned int frames1;
+    unsigned int offset1 = 0;
+    unsigned int frames1 = 0;
     const char *step = "";
     uint32_t mmap_size;
 
@@ -4558,7 +4987,9 @@
 
         if (do_stop) {
             if (in->pcm) {
+                ATRACE_BEGIN("pcm_in_close");
                 pcm_close(in->pcm);
+                ATRACE_END();
                 in->pcm = NULL;
             }
             status = stop_input_stream(in);
@@ -4705,10 +5136,16 @@
         return NULL;
     }
 
-    ALOGV("%s: enter: keys - %s", __func__, keys);
+    ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
 
     voice_extn_in_get_parameters(in, query, reply);
 
+    stream_get_parameter_channels(query, reply,
+                                  &in->supported_channel_masks[0]);
+    stream_get_parameter_formats(query, reply,
+                                 &in->supported_formats[0]);
+    stream_get_parameter_rates(query, reply,
+                               &in->supported_sample_rates[0]);
     str = str_parms_to_str(reply);
     str_parms_destroy(query);
     str_parms_destroy(reply);
@@ -4845,6 +5282,8 @@
     effect_descriptor_t desc;
 
     status = (*effect)->get_descriptor(effect, &desc);
+    ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
+
     if (status != 0)
         return status;
 
@@ -4854,14 +5293,22 @@
             in->enable_aec != enable &&
             (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
         in->enable_aec = enable;
-        if (!in->standby)
-            select_devices(in->dev, in->usecase);
+        if (!in->standby) {
+            if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
+                select_devices(in->dev, in->usecase);
+        }
+
     }
     if (in->enable_ns != enable &&
             (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
         in->enable_ns = enable;
-        if (!in->standby)
-            select_devices(in->dev, in->usecase);
+        if (!in->standby) {
+            if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+                if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
+                    select_devices(in->dev, in->usecase);
+            } else
+                select_devices(in->dev, in->usecase);
+        }
     }
     pthread_mutex_unlock(&in->dev->lock);
     pthread_mutex_unlock(&in->lock);
@@ -5043,6 +5490,10 @@
     audio_format_t format;
     struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
     bool is_direct_passthough = false;
+    bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+    bool is_usb_dev = audio_is_usb_out_device(devices) &&
+                      (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
+    bool direct_dev = is_hdmi || is_usb_dev;
 
     *stream_out = NULL;
 
@@ -5087,25 +5538,41 @@
         (property_get_bool("audio.matrix.limiter.enable", false)))
         platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
 
-    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
-        (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
-        pthread_mutex_lock(&adev->lock);
-        ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
-        ret = read_hdmi_sink_caps(out);
-        pthread_mutex_unlock(&adev->lock);
-        if (ret != 0) {
+    if (audio_is_linear_pcm(out->format) &&
+        out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
+       pthread_mutex_lock(&adev->lock);
+       if (is_hdmi) {
+           ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
+           ret = read_hdmi_sink_caps(out);
+       } else if (is_usb_dev) {
+            ret = read_usb_sup_params_and_compare(true /*is_playback*/,
+                                                  &config->format,
+                                                  &out->supported_formats[0],
+                                                  MAX_SUPPORTED_FORMATS,
+                                                  &config->channel_mask,
+                                                  &out->supported_channel_masks[0],
+                                                  MAX_SUPPORTED_CHANNEL_MASKS,
+                                                  &config->sample_rate,
+                                                  &out->supported_sample_rates[0],
+                                                  MAX_SUPPORTED_SAMPLE_RATES);
+            ALOGV("plugged dev USB ret %d", ret);
+       } else {
+           ret = -1;
+       }
+       pthread_mutex_unlock(&adev->lock);
+       if (ret != 0) {
             if (ret == -ENOSYS) {
                 /* ignore and go with default */
                 ret = 0;
             } else {
-                ALOGE("error reading hdmi sink caps");
+                ALOGE("error reading direct dev sink caps");
                 goto error_open;
             }
         }
     }
 
     /* Init use case and pcm_config */
-#ifndef COMPRES_ENABLED
+#ifndef COMPRESS_VOIP_ENABLED
     if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
         (out->sample_rate == 8000 || out->sample_rate == 16000 ||
          out->sample_rate == 32000 || out->sample_rate == 48000)) {
@@ -5118,7 +5585,7 @@
         out->config.rate = out->sample_rate;
 
 #else
-    } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
+    if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
                (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
                (voice_extn_compress_voip_is_config_supported(config))) {
         ret = voice_extn_compress_voip_open_output_stream(out);
@@ -5128,6 +5595,19 @@
             goto error_open;
         }
 #endif
+    } else if (audio_is_linear_pcm(out->format) &&
+        out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
+        out->channel_mask = config->channel_mask;
+        out->sample_rate = config->sample_rate;
+        out->format = config->format;
+        out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
+        // does this change?
+        out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
+        out->config.rate = config->sample_rate;
+        out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
+        out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
+                                                         audio_bytes_per_sample(config->format));
+        out->config.format = pcm_format_from_audio_format(out->format);
     } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
                (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
         pthread_mutex_lock(&adev->lock);
@@ -5183,8 +5663,8 @@
         out->stream.pause = out_pause;
         out->stream.resume = out_resume;
         out->stream.flush = out_flush;
+        out->stream.set_callback = out_set_callback;
         if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-            out->stream.set_callback = out_set_callback;
             out->stream.drain = out_drain;
             out->usecase = get_offload_usecase(adev, true /* is_compress */);
             ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
@@ -5615,7 +6095,7 @@
     struct audio_device *adev = out->dev;
     int ret = 0;
 
-    ALOGD("%s: enter:stream_handle(%p)",__func__, out);
+    ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
 
     // must deregister from sndmonitor first to prevent races
     // between the callback and close_stream
@@ -5744,19 +6224,10 @@
             status = -EINVAL;
         }
         if (status == 0) {
-            if (adev->speaker_lr_swap != reverse_speakers) {
-                adev->speaker_lr_swap = reverse_speakers;
-                // only update the selected device if there is active pcm playback
-                struct audio_usecase *usecase;
-                struct listnode *node;
-                list_for_each(node, &adev->usecase_list) {
-                    usecase = node_to_item(node, struct audio_usecase, list);
-                    if (usecase->type == PCM_PLAYBACK) {
-                        select_devices(adev, usecase->id);
-                        break;
-                    }
-                }
-            }
+            // 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);
         }
     }
 
@@ -6014,6 +6485,42 @@
             false /* is_low_latency: since we don't know, be conservative */);
 }
 
+static bool adev_input_allow_hifi_record(struct audio_device *adev,
+                                         audio_devices_t devices,
+                                         audio_input_flags_t flags,
+                                         audio_source_t source) {
+    const bool allowed = true;
+
+    if (!audio_is_usb_in_device(devices))
+        return !allowed;
+
+    switch (flags) {
+        case AUDIO_INPUT_FLAG_NONE:
+        case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
+            break;
+        default:
+            return !allowed;
+    }
+
+    switch (source) {
+        case AUDIO_SOURCE_DEFAULT:
+        case AUDIO_SOURCE_MIC:
+        case AUDIO_SOURCE_UNPROCESSED:
+            break;
+        default:
+            return !allowed;
+    }
+
+    switch (adev->mode) {
+        case 0:
+            break;
+        default:
+            return !allowed;
+    }
+
+    return allowed;
+}
+
 static int adev_open_input_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
@@ -6029,11 +6536,26 @@
     int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
     bool is_low_latency = false;
     bool channel_mask_updated = false;
+    bool is_usb_dev = audio_is_usb_in_device(devices);
+    bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
+                                                            devices,
+                                                            flags,
+                                                            source);
 
     *stream_in = NULL;
-    if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
-        ALOGE("%s: invalid input parameters", __func__);
-        return -EINVAL;
+
+    if (!(is_usb_dev && may_use_hifi_record)) {
+        if (config->sample_rate == 0)
+            config->sample_rate = 48000;
+        if (config->channel_mask == AUDIO_CHANNEL_NONE)
+            config->channel_mask = AUDIO_CHANNEL_IN_MONO;
+        if (config->format == AUDIO_FORMAT_DEFAULT)
+            config->format = AUDIO_FORMAT_PCM_16_BIT;
+
+        channel_count = audio_channel_count_from_in_mask(config->channel_mask);
+
+        if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
+            return -EINVAL;
     }
 
     in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
@@ -6069,47 +6591,31 @@
     in->source = source;
     in->dev = adev;
     in->standby = 1;
-    in->channel_mask = config->channel_mask;
     in->capture_handle = handle;
     in->flags = flags;
 
-    in->usecase = USECASE_AUDIO_RECORD;
-    if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
-        (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
-        is_low_latency = true;
-#if LOW_LATENCY_CAPTURE_USE_CASE
-        in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
-#endif
-        in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
-    }
-    in->format = config->format;
-    if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
-               ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
-        in->realtime = 0;
-        in->usecase = USECASE_AUDIO_RECORD_MMAP;
-        in->config = pcm_config_mmap_capture;
-        in->stream.start = in_start;
-        in->stream.stop = in_stop;
-        in->stream.create_mmap_buffer = in_create_mmap_buffer;
-        in->stream.get_mmap_position = in_get_mmap_position;
-        in->af_period_multiplier = 1;
-        ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
-    } else if (in->realtime) {
-        in->config = pcm_config_audio_capture_rt;
-        in->sample_rate = in->config.rate;
-        in->af_period_multiplier = af_period_multiplier;
-    } else {
-        in->config = pcm_config_audio_capture;
-        in->config.rate = config->sample_rate;
-        in->sample_rate = config->sample_rate;
-        in->af_period_multiplier = 1;
-    }
-    in->bit_width = 16;
-
     /* restrict 24 bit capture for unprocessed source only
      * for other sources if 24 bit requested reject 24 and set 16 bit capture only
      */
-    if (config->format == AUDIO_FORMAT_DEFAULT) {
+    if (is_usb_dev && may_use_hifi_record) {
+        /* HiFi record selects an appropriate format, channel, rate combo
+           depending on sink capabilities*/
+        ret = read_usb_sup_params_and_compare(false /*is_playback*/,
+                                              &config->format,
+                                              &in->supported_formats[0],
+                                              MAX_SUPPORTED_FORMATS,
+                                              &config->channel_mask,
+                                              &in->supported_channel_masks[0],
+                                              MAX_SUPPORTED_CHANNEL_MASKS,
+                                              &config->sample_rate,
+                                              &in->supported_sample_rates[0],
+                                              MAX_SUPPORTED_SAMPLE_RATES);
+        if (ret != 0) {
+            ret = -EINVAL;
+            goto err_open;
+        }
+        channel_count = audio_channel_count_from_in_mask(config->channel_mask);
+    } else if (config->format == AUDIO_FORMAT_DEFAULT) {
         config->format = AUDIO_FORMAT_PCM_16_BIT;
     } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
                (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
@@ -6147,6 +6653,42 @@
         }
     }
 
+    in->channel_mask = config->channel_mask;
+    in->format = config->format;
+
+    in->usecase = USECASE_AUDIO_RECORD;
+    if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
+            (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
+        is_low_latency = true;
+#if LOW_LATENCY_CAPTURE_USE_CASE
+        in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
+#endif
+        in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
+    }
+
+    if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
+               ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
+        in->realtime = 0;
+        in->usecase = USECASE_AUDIO_RECORD_MMAP;
+        in->config = pcm_config_mmap_capture;
+        in->stream.start = in_start;
+        in->stream.stop = in_stop;
+        in->stream.create_mmap_buffer = in_create_mmap_buffer;
+        in->stream.get_mmap_position = in_get_mmap_position;
+        in->af_period_multiplier = 1;
+        ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
+    } else if (in->realtime) {
+        in->config = pcm_config_audio_capture_rt;
+        in->sample_rate = in->config.rate;
+        in->af_period_multiplier = af_period_multiplier;
+    } else {
+        in->config = pcm_config_audio_capture;
+        in->config.rate = config->sample_rate;
+        in->sample_rate = config->sample_rate;
+        in->af_period_multiplier = 1;
+    }
+    in->bit_width = 16;
+
     /* Update config params with the requested sample rate and channels */
     if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
           (adev->mode != AUDIO_MODE_IN_CALL)) {
@@ -6154,7 +6696,20 @@
         goto err_open;
     }
 
-    if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
+    if (is_usb_dev && may_use_hifi_record) {
+        in->usecase = USECASE_AUDIO_RECORD_HIFI;
+        in->config = pcm_config_audio_capture;
+        frame_size = audio_stream_in_frame_size(&in->stream);
+        buffer_size = get_input_buffer_size(config->sample_rate,
+                                            config->format,
+                                            channel_count,
+                                            false /*is_low_latency*/);
+        in->config.period_size = buffer_size / frame_size;
+        in->config.rate = config->sample_rate;
+        in->af_period_multiplier = 1;
+        in->config.format = pcm_format_from_audio_format(config->format);
+        in->config.channels = channel_count;
+    } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
              (in->device == AUDIO_DEVICE_IN_PROXY)) {
         if (config->sample_rate == 0)
             config->sample_rate = AFE_PROXY_SAMPLING_RATE;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index fda0672..56ee9d0 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -90,6 +90,19 @@
 #define MAX_PERF_LOCK_OPTS 20
 
 #define MAX_STREAM_PROFILE_STR_LEN 32
+typedef enum {
+    EFFECT_NONE = 0,
+    EFFECT_AEC,
+    EFFECT_NS,
+    EFFECT_MAX
+} effect_type_t;
+
+struct audio_effect_config {
+    uint32_t module_id;
+    uint32_t instance_id;
+    uint32_t param_id;
+    uint32_t param_value;
+};
 
 #define MAX_MIXER_PATH_LEN 64
 
@@ -119,6 +132,7 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
     USECASE_AUDIO_PLAYBACK_ULL,
     USECASE_AUDIO_PLAYBACK_MMAP,
+    USECASE_AUDIO_PLAYBACK_HIFI,
 
     /* FM usecase */
     USECASE_AUDIO_PLAYBACK_FM,
@@ -135,6 +149,7 @@
     USECASE_AUDIO_RECORD_COMPRESS4,
     USECASE_AUDIO_RECORD_LOW_LATENCY,
     USECASE_AUDIO_RECORD_FM_VIRTUAL,
+    USECASE_AUDIO_RECORD_HIFI,
 
     USECASE_AUDIO_PLAYBACK_VOIP,
     USECASE_AUDIO_RECORD_VOIP,
@@ -361,6 +376,11 @@
     struct audio_device *dev;
     card_status_t card_status;
     int capture_started;
+
+    /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
+    audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
+    audio_format_t supported_formats[MAX_SUPPORTED_FORMATS + 1];
+    uint32_t supported_sample_rates[MAX_SUPPORTED_SAMPLE_RATES + 1];
 };
 
 typedef enum {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 6dfa0eb..45b02e3 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -165,6 +165,8 @@
 #define MAX_CAL_NAME 20
 #define MAX_MIME_TYPE_LENGTH 30
 
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
 char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
         [WCD9XXX_ANC_CAL] = "anc_cal",
         [WCD9XXX_MBHC_CAL] = "mbhc_cal",
@@ -249,6 +251,7 @@
     bool external_spk_1;
     bool external_spk_2;
     bool external_mic;
+    bool speaker_lr_swap;
     int  fluence_type;
     char fluence_cap[PROPERTY_VALUE_MAX];
     int  fluence_mode;
@@ -311,6 +314,8 @@
                                            LOWLATENCY_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
                                         MULTIMEDIA2_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE,
+                                     MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
     /* Below entries are initialized with invalid values
@@ -335,6 +340,8 @@
                                           LOWLATENCY_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE,
                                   MULTIMEDIA2_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_HIFI] = {MULTIMEDIA2_PCM_DEVICE,
+                                   MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
     [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
     [USECASE_AUDIO_HFP_SCO_WB] = {HFP_PCM_RX, HFP_SCO_RX},
@@ -546,6 +553,23 @@
 // Platform specific backend bit width table
 static int backend_bit_width_table[SND_DEVICE_MAX] = {0};
 
+static struct audio_effect_config effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_MAX] = {
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FLUENCE_PROV2,  0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_AEC] = {TX_VOICE_DM_FV5_BROADSIDE, 0x0,
+                                                                 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_NS] = {TX_VOICE_DM_FV5_BROADSIDE, 0x0,
+                                                                0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+};
+
 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
 static int acdb_device_table[SND_DEVICE_MAX] = {
     [SND_DEVICE_NONE] = -1,
@@ -2881,6 +2905,35 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d",
+            __func__, snd_device);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if (effect_config == NULL) {
+        ALOGE("%s: Invalid effect_config", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s: snd_device = %d module_id = %d",
+            __func__, snd_device, effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+    memcpy(effect_config, &effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type],
+           sizeof(struct audio_effect_config));
+
+done:
+    return ret;
+}
+
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
 {
     int ret = 0;
@@ -2899,6 +2952,29 @@
     return ret;
 }
 
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d",
+            __func__, snd_device);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+           effect_config.instance_id, effect_config.param_id,
+           effect_config.param_value);
+    effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+
+done:
+    return ret;
+}
+
 int platform_set_acdb_metainfo_key(void *platform, char *name, int key)
 {
     struct meta_key_list *key_info;
@@ -3993,6 +4069,148 @@
     return snd_device;
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    }
+
+    return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE && adev->active_input->enable_aec &&
+        adev->active_input->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               adev->active_input->enable_aec) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+       } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               adev->active_input->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, false, out_device);
+    } else
+        platform_set_echo_reference(adev, false, out_device);
+
+    return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -4218,97 +4436,7 @@
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
         if (adev->active_input) {
-            if (my_data->fluence_type != FLUENCE_NONE &&
-                adev->active_input->enable_aec &&
-                adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
-                             (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
-                        } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                             (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
-                    snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_aec) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
-                            (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
-                        } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
-                   snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
-                            (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
-                        } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                            (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, false, out_device);
-            } else
-                platform_set_echo_reference(adev, false, out_device);
+            snd_device = get_snd_device_for_voice_comm(my_data, out_device, in_device);
         }
     } else if (source == AUDIO_SOURCE_MIC) {
         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
@@ -6305,12 +6433,7 @@
     int iter_i = 0;
     int iter_j = 0;
     int length = 0;
-    int pan_scale_data[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
-
-    if (sizeof(mm_params) > MAX_LENGTH_MIXER_CONTROL_IN_INT) {
-        ret = -EINVAL;
-        goto end;
-    }
+    char *pan_scale_data = NULL;
 
     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
                           "Audio Stream %d Pan Scale Control", snd_id);
@@ -6323,40 +6446,60 @@
         ret = -EINVAL;
         goto end;
     }
-    pan_scale_data[length++] = mm_params.num_output_channels;
-    pan_scale_data[length++] = mm_params.num_input_channels;
+    pan_scale_data = (char *) calloc(1, sizeof(mm_params));
+    if (!pan_scale_data) {
+        ret = -ENOMEM;
+        goto end;
+    }
+    memcpy(&pan_scale_data[length], &mm_params.num_output_channels,
+                              sizeof(mm_params.num_output_channels));
+    length += sizeof(mm_params.num_output_channels);
+    memcpy(&pan_scale_data[length], &mm_params.num_input_channels,
+                              sizeof(mm_params.num_input_channels));
+    length += sizeof(mm_params.num_input_channels);
 
-    pan_scale_data[length++] = mm_params.has_output_channel_map;
+    memcpy(&pan_scale_data[length], &mm_params.has_output_channel_map,
+                              sizeof(mm_params.has_output_channel_map));
+    length += sizeof(mm_params.has_output_channel_map);
     if (mm_params.has_output_channel_map &&
         mm_params.num_output_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_output_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            pan_scale_data[length++] = mm_params.output_channel_map[iter_i];
-    else {
+        mm_params.num_output_channels > 0) {
+        memcpy(&pan_scale_data[length], mm_params.output_channel_map,
+                (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0])));
+        length += (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
 
-    pan_scale_data[length++] = mm_params.has_input_channel_map;
+    memcpy(&pan_scale_data[length], &mm_params.has_input_channel_map,
+                                sizeof(mm_params.has_input_channel_map));
+    length += sizeof(mm_params.has_input_channel_map);
     if (mm_params.has_input_channel_map &&
         mm_params.num_input_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_input_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_input_channels; iter_i++)
-            pan_scale_data[length++] = mm_params.input_channel_map[iter_i];
-    else {
+        mm_params.num_input_channels > 0) {
+        memcpy(&pan_scale_data[length], mm_params.input_channel_map,
+               (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0])));
+            length += (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
-
-    pan_scale_data[length++] = mm_params.has_mixer_coeffs;
+    pan_scale_data[length] = mm_params.has_mixer_coeffs;
+    length += sizeof(mm_params.has_mixer_coeffs);
     if (mm_params.has_mixer_coeffs)
         for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++)
-                pan_scale_data[length++] =
-                                    mm_params.mixer_coeffs[iter_i][iter_j];
+            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++) {
+                 memcpy(&pan_scale_data[length],
+                        &mm_params.mixer_coeffs[iter_i][iter_j],
+                        (sizeof(mm_params.mixer_coeffs[0][0])));
+                 length += (sizeof(mm_params.mixer_coeffs[0][0]));
+            }
 
     ret = mixer_ctl_set_array(ctl, pan_scale_data, length);
 end:
+    if (pan_scale_data)
+        free(pan_scale_data);
     return ret;
 }
 
@@ -6369,20 +6512,13 @@
     struct audio_device *adev = my_data->adev;
     struct mixer_ctl *ctl;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
-    int downmix_param_data[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
+    char *downmix_param_data = NULL;
     int ret = 0;
     int iter_i = 0;
     int iter_j = 0;
     int length = 0;
     int be_idx = 0;
 
-    if ((sizeof(mm_params) +
-         sizeof(be_idx)) >
-        MAX_LENGTH_MIXER_CONTROL_IN_INT) {
-        ret = -EINVAL;
-        goto end;
-    }
-
     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
                           "Audio Device %d Downmix Control", snd_id);
     ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);
@@ -6392,45 +6528,66 @@
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
               __func__, mixer_ctl_name);
         ret = -EINVAL;
-        goto end;
     }
 
+    downmix_param_data = (char *) calloc(1, sizeof(mm_params) + sizeof(be_idx));
+    if (!downmix_param_data) {
+        ret = -ENOMEM;
+        goto end;
+    }
     be_idx = platform_get_snd_device_backend_index(snd_device);
-    downmix_param_data[length]   = be_idx;
-    downmix_param_data[length++] = mm_params.num_output_channels;
-    downmix_param_data[length++] = mm_params.num_input_channels;
+    memcpy(&downmix_param_data[length], &be_idx, sizeof(be_idx));
+    length += sizeof(be_idx);
+    memcpy(&downmix_param_data[length], &mm_params.num_output_channels,
+                                    sizeof(mm_params.num_output_channels));
+    length += sizeof(mm_params.num_output_channels);
+    memcpy(&downmix_param_data[length], &mm_params.num_input_channels,
+                                    sizeof(mm_params.num_input_channels));
+    length += sizeof(mm_params.num_input_channels);
 
-    downmix_param_data[length++] = mm_params.has_output_channel_map;
+    memcpy(&downmix_param_data[length], &mm_params.has_output_channel_map,
+                                   sizeof(mm_params.has_output_channel_map));
+    length += sizeof(mm_params.has_output_channel_map);
     if (mm_params.has_output_channel_map &&
         mm_params.num_output_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_output_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            downmix_param_data[length++] = mm_params.output_channel_map[iter_i];
-    else {
+        mm_params.num_output_channels > 0) {
+        memcpy(&downmix_param_data[length], mm_params.output_channel_map,
+                (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0])));
+        length += (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
 
-    downmix_param_data[length++] = mm_params.has_input_channel_map;
+    memcpy(&downmix_param_data[length], &mm_params.has_input_channel_map,
+                                   sizeof(mm_params.has_input_channel_map));
+    length += sizeof(mm_params.has_input_channel_map);
     if (mm_params.has_input_channel_map &&
         mm_params.num_input_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_input_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_input_channels; iter_i++)
-            downmix_param_data[length++] = mm_params.input_channel_map[iter_i];
-    else {
+        mm_params.num_input_channels > 0) {
+        memcpy(&downmix_param_data[length], mm_params.input_channel_map,
+                (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0])));
+            length += (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
-
-    downmix_param_data[length++] = mm_params.has_mixer_coeffs;
+    memcpy(&downmix_param_data[length], &mm_params.has_mixer_coeffs,
+                                    sizeof(mm_params.has_mixer_coeffs));
+    length += sizeof(mm_params.has_mixer_coeffs);
     if (mm_params.has_mixer_coeffs)
         for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++)
-                downmix_param_data[length++] =
-                                       mm_params.mixer_coeffs[iter_i][iter_j];
+            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++) {
+                memcpy((uint32_t *) &downmix_param_data[length],
+                        &mm_params.mixer_coeffs[iter_i][iter_j],
+                        (sizeof(mm_params.mixer_coeffs[0][0])));
+                length += (sizeof(mm_params.mixer_coeffs[0][0]));
+            }
 
     ret = mixer_ctl_set_array(ctl, downmix_param_data, length);
 end:
+    if (downmix_param_data)
+        free(downmix_param_data);
     return ret;
 }
 
@@ -7171,6 +7328,7 @@
     bool ret = false;
 
     if (snd_device == SND_DEVICE_OUT_SPEAKER ||
+        snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
         snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
         snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
         snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
@@ -7492,6 +7650,151 @@
     return my_data->max_mic_count;
 }
 
+#define DEFAULT_NOMINAL_SPEAKER_GAIN 20
+int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_up_gain) {
+    // backup_gain: gain to try to set in case of an error during ramp
+    int start_gain, end_gain, step, backup_gain, i;
+    bool error = false;
+    const char *mixer_ctl_name_gain_left = "Left Speaker Gain";
+    const char *mixer_ctl_name_gain_right = "Right Speaker Gain";
+    struct mixer_ctl *ctl_left = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_left);
+    struct mixer_ctl *ctl_right = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_right);
+    if (!ctl_left || !ctl_right) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s or %s, not applying speaker gain ramp",
+                      __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right);
+        return -EINVAL;
+    } else if ((mixer_ctl_get_num_values(ctl_left) != 1)
+            || (mixer_ctl_get_num_values(ctl_right) != 1)) {
+        ALOGE("%s: Unexpected num values for mixer cmd - %s or %s, not applying speaker gain ramp",
+                              __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right);
+        return -EINVAL;
+    }
+    if (ramp_up) {
+        start_gain = 0;
+        end_gain = target_ramp_up_gain > 0 ? target_ramp_up_gain : DEFAULT_NOMINAL_SPEAKER_GAIN;
+        step = +1;
+        backup_gain = end_gain;
+    } else {
+        // using same gain on left and right
+        const int left_gain = mixer_ctl_get_value(ctl_left, 0);
+        start_gain = left_gain > 0 ? left_gain : DEFAULT_NOMINAL_SPEAKER_GAIN;
+        end_gain = 0;
+        step = -1;
+        backup_gain = start_gain;
+    }
+    for (i = start_gain ; i != (end_gain + step) ; i += step) {
+        if (mixer_ctl_set_value(ctl_left, 0, i)) {
+            ALOGE("%s: error setting %s to %d during gain ramp",
+                    __func__, mixer_ctl_name_gain_left, i);
+            error = true;
+            break;
+        }
+        if (mixer_ctl_set_value(ctl_right, 0, i)) {
+            ALOGE("%s: error setting %s to %d during gain ramp",
+                    __func__, mixer_ctl_name_gain_right, i);
+            error = true;
+            break;
+        }
+        usleep(1000);
+    }
+    if (error) {
+        // an error occured during the ramp, let's still try to go back to a safe volume
+        if (mixer_ctl_set_value(ctl_left, 0, backup_gain)) {
+            ALOGE("%s: error restoring left gain to %d", __func__, backup_gain);
+        }
+        if (mixer_ctl_set_value(ctl_right, 0, backup_gain)) {
+            ALOGE("%s: error restoring right gain to %d", __func__, backup_gain);
+        }
+    }
+    return start_gain;
+}
+
+int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels)
+{
+    const char *mixer_ctl_name = "Swap channel";
+    struct mixer_ctl *ctl;
+    const char *mixer_path;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+    // forced to set to swap, but device not rotated ... ignore set
+    if (swap_channels && !my_data->speaker_lr_swap)
+        return 0;
+
+    ALOGV("%s:", __func__);
+
+    if (swap_channels)
+        mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE);
+    else
+        mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER);
+
+    audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+
+    if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) {
+        ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels);
+        return -EINVAL;
+    }
+
+    ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ",
+           swap_channels?"R --> L":"L --> R");
+
+    return 0;
+}
+
+int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels)
+{
+    // only update if there is active pcm playback on speaker
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+    my_data->speaker_lr_swap = swap_channels;
+
+    return platform_set_swap_channels(adev, swap_channels);
+}
+
+int platform_set_swap_channels(struct audio_device *adev, bool swap_channels)
+{
+    // only update if there is active pcm playback on speaker
+    struct audio_usecase *usecase;
+    struct listnode *node;
+
+    // do not swap channels in audio modes with concurrent capture and playback
+    // as this may break the echo reference
+    if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) {
+        ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode);
+        return 0;
+    }
+
+    list_for_each(node, &adev->usecase_list) {
+        usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_PLAYBACK &&
+                usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+            /*
+             * If acdb tuning is different for SPEAKER_REVERSE, it is must
+             * to perform device switch to disable the current backend to
+             * enable it with new acdb data.
+             */
+            if (acdb_device_table[SND_DEVICE_OUT_SPEAKER] !=
+                acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) {
+                const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1);
+                select_devices(adev, usecase->id);
+                if (initial_skpr_gain != -EINVAL)
+                    ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain);
+
+            } else {
+                platform_set_swap_mixer(adev, swap_channels);
+            }
+            break;
+        }
+    }
+
+    return 0;
+}
+
 bool platform_add_gain_level_mapping(struct amp_db_and_gain_table *tbl_entry __unused)
 {
     return false;
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 13247ff..d128d0f 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -299,6 +299,10 @@
 #define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240
 #define LOW_LATENCY_CAPTURE_USE_CASE 1
 
+#define HIFI_BUFFER_OUTPUT_PERIOD_SIZE 1920
+#define HIFI_BUFFER_OUTPUT_PERIOD_DURATION 40 /* 40 millisecs */
+#define HIFI_BUFFER_OUTPUT_PERIOD_COUNT 2
+
 #define HDMI_MULTI_PERIOD_SIZE  336
 #define HDMI_MULTI_PERIOD_COUNT 8
 #define HDMI_MULTI_DEFAULT_CHANNEL_COUNT 6
@@ -379,6 +383,11 @@
 #define PLATFORM_MAX_MIC_COUNT "input_mic_max_count"
 #define PLATFORM_DEFAULT_MIC_COUNT 2
 
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 /* CSD-CLIENT related functions */
 typedef int (*init_t)();
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 61ef223..64dde86 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -140,6 +140,8 @@
 #define MAX_CAL_NAME 20
 #define MAX_MIME_TYPE_LENGTH 30
 
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
 #ifdef DYNAMIC_LOG_ENABLED
 extern void log_utils_init(void);
 extern void log_utils_deinit(void);
@@ -222,6 +224,7 @@
     bool external_spk_1;
     bool external_spk_2;
     bool external_mic;
+    bool speaker_lr_swap;
     int  fluence_type;
     int  fluence_mode;
     char fluence_cap[PROPERTY_VALUE_MAX];
@@ -281,6 +284,8 @@
                                             MULTIMEDIA3_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
                                          MULTIMEDIA2_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE,
+                                     MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD2] =
@@ -310,6 +315,8 @@
                                           LOWLATENCY_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE,
                                   MULTIMEDIA2_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_HIFI] = {MULTIMEDIA2_PCM_DEVICE,
+                                   MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
     [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
     [USECASE_AUDIO_HFP_SCO_WB] = {HFP_PCM_RX, HFP_SCO_RX},
@@ -511,15 +518,32 @@
     [SND_DEVICE_IN_HANDSET_TMIC] = "three-mic",
     [SND_DEVICE_IN_VOICE_REC_TMIC] = "three-mic",
     [SND_DEVICE_IN_UNPROCESSED_MIC] = "unprocessed-mic",
-    [SND_DEVICE_IN_UNPROCESSED_STEREO_MIC] = "voice-rec-dmic-ef",
-    [SND_DEVICE_IN_UNPROCESSED_THREE_MIC] = "three-mic",
-    [SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = "quad-mic",
-    [SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = "headset-mic",
+    [SND_DEVICE_IN_UNPROCESSED_STEREO_MIC] = "unprocessed-stereo-mic",
+    [SND_DEVICE_IN_UNPROCESSED_THREE_MIC] = "unprocessed-three-mic",
+    [SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = "unprocessed-quad-mic",
+    [SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = "unprocessed-headset-mic",
 };
 
 // Platform specific backend bit width table
 static int backend_bit_width_table[SND_DEVICE_MAX] = {0};
 
+static struct audio_effect_config effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_MAX] = {
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FLUENCE_PROV2,  0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_AEC] = {TX_VOICE_DM_FV5_BROADSIDE, 0x0,
+                                                                 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_NS] = {TX_VOICE_DM_FV5_BROADSIDE, 0x0,
+                                                                0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+    [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+};
+
 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
 static int acdb_device_table[SND_DEVICE_MAX] = {
     [SND_DEVICE_NONE] = -1,
@@ -2642,6 +2666,35 @@
     return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
 }
 
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d",
+            __func__, snd_device);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    if(effect_config == NULL) {
+        ALOGE("%s: Invalid effect_config", __func__);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s: snd_device = %d module_id = %d",
+            __func__, snd_device, effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+    memcpy(effect_config, &effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type],
+           sizeof(struct audio_effect_config));
+
+done:
+    return ret;
+}
+
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
 {
     int ret = 0;
@@ -2660,6 +2713,29 @@
     return ret;
 }
 
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type)
+{
+    int ret = 0;
+
+    if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+        (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_MAX)) {
+        ALOGE("%s: Invalid snd_device = %d",
+            __func__, snd_device);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+           effect_config.instance_id, effect_config.param_id,
+           effect_config.param_value);
+    effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+
+done:
+    return ret;
+}
+
 int platform_set_acdb_metainfo_key(void *platform, char *name, int key)
 {
     struct meta_key_list *key_info;
@@ -3726,6 +3802,148 @@
     return snd_device;
 }
 
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    }
+
+    return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+                                                  audio_devices_t out_device,
+                                                  audio_devices_t in_device)
+{
+    struct audio_device *adev = my_data->adev;
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    if (my_data->fluence_type != FLUENCE_NONE && adev->active_input->enable_aec &&
+        adev->active_input->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               adev->active_input->enable_aec) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+       } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
+            snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+        }
+        platform_set_echo_reference(adev, true, out_device);
+    } else if (my_data->fluence_type != FLUENCE_NONE &&
+               adev->active_input->enable_ns) {
+        if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+            if (my_data->fluence_in_spkr_mode) {
+                if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
+                    (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+                    snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
+                } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                           (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                    if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+                    else
+                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+                }
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
+                (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+                snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+                adev->acdb_settings |= DMIC_FLAG;
+            } else
+                snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+        }
+        platform_set_echo_reference(adev, false, out_device);
+    } else
+        platform_set_echo_reference(adev, false, out_device);
+
+    return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -3965,97 +4183,7 @@
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
         if (adev->active_input) {
-            if (my_data->fluence_type != FLUENCE_NONE &&
-                    adev->active_input->enable_aec &&
-                    adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
-                            (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
-                        } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                                   (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
-                    snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_aec) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
-                            (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
-                        } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                                   (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-               } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE) {
-                    snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
-                }
-                platform_set_echo_reference(adev, true, out_device);
-            } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_ns) {
-                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
-                    if (my_data->fluence_in_spkr_mode) {
-                        if ((my_data->fluence_type & FLUENCE_QUAD_MIC) &&
-                            (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                            snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
-                        } else if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                                   (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                            if (my_data->fluence_mode == FLUENCE_BROADSIDE)
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
-                            else
-                                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
-                        }
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                    if ((my_data->fluence_type & FLUENCE_DUAL_MIC) &&
-                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
-                        adev->acdb_settings |= DMIC_FLAG;
-                    } else
-                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
-                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
-                }
-                platform_set_echo_reference(adev, false, out_device);
-            } else
-                platform_set_echo_reference(adev, false, out_device);
+            snd_device = get_snd_device_for_voice_comm(my_data, out_device, in_device);
         }
     } else if (source == AUDIO_SOURCE_MIC) {
         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
@@ -6123,7 +6251,7 @@
     int iter_i = 0;
     int iter_j = 0;
     int length = 0;
-    int *pan_scale_data = NULL;
+    char *pan_scale_data = NULL;
 
     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
                           "Audio Stream %d Pan Scale Control", snd_id);
@@ -6136,41 +6264,55 @@
         ret = -EINVAL;
         goto end;
     }
-    pan_scale_data = (int* ) calloc(1, sizeof(mm_params));
+    pan_scale_data = (char *) calloc(1, sizeof(mm_params));
     if (!pan_scale_data) {
         ret = -ENOMEM;
         goto end;
     }
-    pan_scale_data[length++] = mm_params.num_output_channels;
-    pan_scale_data[length++] = mm_params.num_input_channels;
+    memcpy(&pan_scale_data[length], &mm_params.num_output_channels,
+                              sizeof(mm_params.num_output_channels));
+    length += sizeof(mm_params.num_output_channels);
+    memcpy(&pan_scale_data[length], &mm_params.num_input_channels,
+                              sizeof(mm_params.num_input_channels));
+    length += sizeof(mm_params.num_input_channels);
 
-    pan_scale_data[length++] = mm_params.has_output_channel_map;
+    memcpy(&pan_scale_data[length], &mm_params.has_output_channel_map,
+                              sizeof(mm_params.has_output_channel_map));
+    length += sizeof(mm_params.has_output_channel_map);
     if (mm_params.has_output_channel_map &&
         mm_params.num_output_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_output_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            pan_scale_data[length++] = mm_params.output_channel_map[iter_i];
-    else {
+        mm_params.num_output_channels > 0) {
+        memcpy(&pan_scale_data[length], mm_params.output_channel_map,
+                (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0])));
+        length += (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
 
-    pan_scale_data[length++] = mm_params.has_input_channel_map;
+    memcpy(&pan_scale_data[length], &mm_params.has_input_channel_map,
+                                sizeof(mm_params.has_input_channel_map));
+    length += sizeof(mm_params.has_input_channel_map);
     if (mm_params.has_input_channel_map &&
         mm_params.num_input_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_input_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_input_channels; iter_i++)
-            pan_scale_data[length++] = mm_params.input_channel_map[iter_i];
-    else {
+        mm_params.num_input_channels > 0) {
+        memcpy(&pan_scale_data[length], mm_params.input_channel_map,
+               (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0])));
+            length += (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
-    pan_scale_data[length++] = mm_params.has_mixer_coeffs;
+    pan_scale_data[length] = mm_params.has_mixer_coeffs;
+    length += sizeof(mm_params.has_mixer_coeffs);
     if (mm_params.has_mixer_coeffs)
         for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++)
-                pan_scale_data[length++] =
-                                    mm_params.mixer_coeffs[iter_i][iter_j];
+            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++) {
+                 memcpy(&pan_scale_data[length],
+                        &mm_params.mixer_coeffs[iter_i][iter_j],
+                        (sizeof(mm_params.mixer_coeffs[0][0])));
+                 length += (sizeof(mm_params.mixer_coeffs[0][0]));
+            }
 
     ret = mixer_ctl_set_array(ctl, pan_scale_data, length);
 end:
@@ -6188,7 +6330,7 @@
     struct audio_device *adev = my_data->adev;
     struct mixer_ctl *ctl;
     char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
-    int *downmix_param_data = NULL;
+    char *downmix_param_data = NULL;
     int ret = 0;
     int iter_i = 0;
     int iter_j = 0;
@@ -6206,44 +6348,59 @@
         ret = -EINVAL;
     }
 
-    downmix_param_data = (int* ) calloc(1, sizeof(mm_params) + sizeof(be_idx));
+    downmix_param_data = (char *) calloc(1, sizeof(mm_params) + sizeof(be_idx));
     if (!downmix_param_data) {
         ret = -ENOMEM;
         goto end;
     }
     be_idx = platform_get_snd_device_backend_index(snd_device);
-    downmix_param_data[length++] = be_idx;
-    downmix_param_data[length++] = mm_params.num_output_channels;
-    downmix_param_data[length++] = mm_params.num_input_channels;
+    memcpy(&downmix_param_data[length], &be_idx, sizeof(be_idx));
+    length += sizeof(be_idx);
+    memcpy(&downmix_param_data[length], &mm_params.num_output_channels,
+                                    sizeof(mm_params.num_output_channels));
+    length += sizeof(mm_params.num_output_channels);
+    memcpy(&downmix_param_data[length], &mm_params.num_input_channels,
+                                    sizeof(mm_params.num_input_channels));
+    length += sizeof(mm_params.num_input_channels);
 
-    downmix_param_data[length++] = mm_params.has_output_channel_map;
+    memcpy(&downmix_param_data[length], &mm_params.has_output_channel_map,
+                                   sizeof(mm_params.has_output_channel_map));
+    length += sizeof(mm_params.has_output_channel_map);
     if (mm_params.has_output_channel_map &&
         mm_params.num_output_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_output_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            downmix_param_data[length++] = mm_params.output_channel_map[iter_i];
-    else {
+        mm_params.num_output_channels > 0) {
+        memcpy(&downmix_param_data[length], mm_params.output_channel_map,
+                (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0])));
+        length += (mm_params.num_output_channels * sizeof(mm_params.output_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
 
-    downmix_param_data[length++] = mm_params.has_input_channel_map;
+    memcpy(&downmix_param_data[length], &mm_params.has_input_channel_map,
+                                   sizeof(mm_params.has_input_channel_map));
+    length += sizeof(mm_params.has_input_channel_map);
     if (mm_params.has_input_channel_map &&
         mm_params.num_input_channels <= MAX_CHANNELS_SUPPORTED &&
-        mm_params.num_input_channels > 0)
-        for (iter_i = 0; iter_i < mm_params.num_input_channels; iter_i++)
-            downmix_param_data[length++] = mm_params.input_channel_map[iter_i];
-    else {
+        mm_params.num_input_channels > 0) {
+        memcpy(&downmix_param_data[length], mm_params.input_channel_map,
+                (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0])));
+            length += (mm_params.num_input_channels * sizeof(mm_params.input_channel_map[0]));
+    } else {
         ret = -EINVAL;
         goto end;
     }
-
-    downmix_param_data[length++] = mm_params.has_mixer_coeffs;
+    memcpy(&downmix_param_data[length], &mm_params.has_mixer_coeffs,
+                                    sizeof(mm_params.has_mixer_coeffs));
+    length += sizeof(mm_params.has_mixer_coeffs);
     if (mm_params.has_mixer_coeffs)
         for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
-            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++)
-                downmix_param_data[length++] =
-                                       mm_params.mixer_coeffs[iter_i][iter_j];
+            for (iter_j = 0; iter_j < mm_params.num_input_channels; iter_j++) {
+                memcpy((uint32_t *) &downmix_param_data[length],
+                        &mm_params.mixer_coeffs[iter_i][iter_j],
+                        (sizeof(mm_params.mixer_coeffs[0][0])));
+                length += (sizeof(mm_params.mixer_coeffs[0][0]));
+            }
 
     ret = mixer_ctl_set_array(ctl, downmix_param_data, length);
 end:
@@ -6836,6 +6993,7 @@
     bool ret = false;
 
     if (snd_device == SND_DEVICE_OUT_SPEAKER ||
+        snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
         snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
         snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
         snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_2_VBAT ||
@@ -7191,6 +7349,151 @@
     return my_data->max_mic_count;
 }
 
+#define DEFAULT_NOMINAL_SPEAKER_GAIN 20
+int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_up_gain) {
+    // backup_gain: gain to try to set in case of an error during ramp
+    int start_gain, end_gain, step, backup_gain, i;
+    bool error = false;
+    const char *mixer_ctl_name_gain_left = "Left Speaker Gain";
+    const char *mixer_ctl_name_gain_right = "Right Speaker Gain";
+    struct mixer_ctl *ctl_left = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_left);
+    struct mixer_ctl *ctl_right = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_right);
+    if (!ctl_left || !ctl_right) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s or %s, not applying speaker gain ramp",
+                      __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right);
+        return -EINVAL;
+    } else if ((mixer_ctl_get_num_values(ctl_left) != 1)
+            || (mixer_ctl_get_num_values(ctl_right) != 1)) {
+        ALOGE("%s: Unexpected num values for mixer cmd - %s or %s, not applying speaker gain ramp",
+                              __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right);
+        return -EINVAL;
+    }
+    if (ramp_up) {
+        start_gain = 0;
+        end_gain = target_ramp_up_gain > 0 ? target_ramp_up_gain : DEFAULT_NOMINAL_SPEAKER_GAIN;
+        step = +1;
+        backup_gain = end_gain;
+    } else {
+        // using same gain on left and right
+        const int left_gain = mixer_ctl_get_value(ctl_left, 0);
+        start_gain = left_gain > 0 ? left_gain : DEFAULT_NOMINAL_SPEAKER_GAIN;
+        end_gain = 0;
+        step = -1;
+        backup_gain = start_gain;
+    }
+    for (i = start_gain ; i != (end_gain + step) ; i += step) {
+        if (mixer_ctl_set_value(ctl_left, 0, i)) {
+            ALOGE("%s: error setting %s to %d during gain ramp",
+                    __func__, mixer_ctl_name_gain_left, i);
+            error = true;
+            break;
+        }
+        if (mixer_ctl_set_value(ctl_right, 0, i)) {
+            ALOGE("%s: error setting %s to %d during gain ramp",
+                    __func__, mixer_ctl_name_gain_right, i);
+            error = true;
+            break;
+        }
+        usleep(1000);
+    }
+    if (error) {
+        // an error occured during the ramp, let's still try to go back to a safe volume
+        if (mixer_ctl_set_value(ctl_left, 0, backup_gain)) {
+            ALOGE("%s: error restoring left gain to %d", __func__, backup_gain);
+        }
+        if (mixer_ctl_set_value(ctl_right, 0, backup_gain)) {
+            ALOGE("%s: error restoring right gain to %d", __func__, backup_gain);
+        }
+    }
+    return start_gain;
+}
+
+int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels)
+{
+    const char *mixer_ctl_name = "Swap channel";
+    struct mixer_ctl *ctl;
+    const char *mixer_path;
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+    // forced to set to swap, but device not rotated ... ignore set
+    if (swap_channels && !my_data->speaker_lr_swap)
+        return 0;
+
+    ALOGV("%s:", __func__);
+
+    if (swap_channels)
+        mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE);
+    else
+        mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER);
+
+    audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+
+    if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) {
+        ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels);
+        return -EINVAL;
+    }
+
+    ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ",
+           swap_channels?"R --> L":"L --> R");
+
+    return 0;
+}
+
+int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels)
+{
+    // only update if there is active pcm playback on speaker
+    struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+    my_data->speaker_lr_swap = swap_channels;
+
+    return platform_set_swap_channels(adev, swap_channels);
+}
+
+int platform_set_swap_channels(struct audio_device *adev, bool swap_channels)
+{
+    // only update if there is active pcm playback on speaker
+    struct audio_usecase *usecase;
+    struct listnode *node;
+
+    // do not swap channels in audio modes with concurrent capture and playback
+    // as this may break the echo reference
+    if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) {
+        ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode);
+        return 0;
+    }
+
+    list_for_each(node, &adev->usecase_list) {
+        usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_PLAYBACK &&
+                usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+            /*
+             * If acdb tuning is different for SPEAKER_REVERSE, it is must
+             * to perform device switch to disable the current backend to
+             * enable it with new acdb data.
+             */
+            if (acdb_device_table[SND_DEVICE_OUT_SPEAKER] !=
+                acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) {
+                const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1);
+                select_devices(adev, usecase->id);
+                if (initial_skpr_gain != -EINVAL)
+                    ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain);
+
+            } else {
+                platform_set_swap_mixer(adev, swap_channels);
+            }
+            break;
+        }
+    }
+
+    return 0;
+}
+
 static struct amp_db_and_gain_table tbl_mapping[MAX_VOLUME_CAL_STEPS];
 static int num_gain_tbl_entry = 0;
 
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index ba1a195..387ef25 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -302,6 +302,9 @@
 #define HDMI_MULTI_DEFAULT_CHANNEL_COUNT 6
 #define HDMI_MULTI_PERIOD_BYTES (HDMI_MULTI_PERIOD_SIZE * HDMI_MULTI_DEFAULT_CHANNEL_COUNT * 2)
 
+#define HIFI_BUFFER_OUTPUT_PERIOD_SIZE 1920
+#define HIFI_BUFFER_OUTPUT_PERIOD_DURATION 40 /* 40 milisecs */
+#define HIFI_BUFFER_OUTPUT_PERIOD_COUNT 2
 
 /* Used in calculating fragment size for pcm offload */
 #define PCM_OFFLOAD_BUFFER_DURATION 80 /* 80 millisecs */
@@ -497,6 +500,11 @@
 #define PLATFORM_MAX_MIC_COUNT "input_mic_max_count"
 #define PLATFORM_DEFAULT_MIC_COUNT 2
 
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
 #define LIB_CSD_CLIENT "libcsd-client.so"
 /* CSD-CLIENT related functions */
 typedef int (*init_t)(bool);
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 924c1a4..4407d2c 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -100,6 +100,12 @@
 int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
 int platform_get_snd_device_acdb_id(snd_device_t snd_device);
 int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width);
+int platform_set_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config effect_config,
+                                      effect_type_t effect_type);
+int platform_get_effect_config_data(snd_device_t snd_device,
+                                      struct audio_effect_config *effect_config,
+                                      effect_type_t effect_type);
 int platform_get_snd_device_bit_width(snd_device_t snd_device);
 int platform_set_acdb_metainfo_key(void *platform, char *name, int key);
 int platform_get_meta_info_key_from_list(void *platform, char *mod_name);
@@ -172,6 +178,8 @@
 int platform_get_usecase_index(const char * usecase);
 int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
 void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device);
+int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels);
+int platform_set_swap_channels(struct audio_device *adev, bool swap_channels);
 void platform_get_device_to_be_id_map(int **be_id_map, int *length);
 
 int platform_set_channel_allocation(void *platform, int channel_alloc);
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 597d1f7..5140911 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -52,6 +52,9 @@
 typedef enum {
     ROOT,
     ACDB,
+    MODULE,
+    AEC,
+    NS,
     BITWIDTH,
     PCM_ID,
     BACKEND_NAME,
@@ -64,6 +67,9 @@
 typedef void (* section_process_fn)(const XML_Char **attr);
 
 static void process_acdb_id(const XML_Char **attr);
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type);
+static void process_effect_aec(const XML_Char **attr);
+static void process_effect_ns(const XML_Char **attr);
 static void process_bit_width(const XML_Char **attr);
 static void process_pcm_id(const XML_Char **attr);
 static void process_backend_name(const XML_Char **attr);
@@ -76,6 +82,8 @@
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
     [ACDB] = process_acdb_id,
+    [AEC] = process_effect_aec,
+    [NS] = process_effect_ns,
     [BITWIDTH] = process_bit_width,
     [PCM_ID] = process_pcm_id,
     [BACKEND_NAME] = process_backend_name,
@@ -102,6 +110,11 @@
  * ...
  * ...
  * </acdb_ids>
+ * <module_ids>
+ * <device name="???" module_id="???"/>
+ * ...
+ * ...
+ * </module_ids>
  * <backend_names>
  * <device name="???" backend="???"/>
  * ...
@@ -279,6 +292,77 @@
     return;
 }
 
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type)
+{
+    int index;
+    struct audio_effect_config effect_config;
+
+    if (strcmp(attr[0], "name") != 0) {
+        ALOGE("%s: 'name' not found, no MODULE ID set!", __func__);
+        goto done;
+    }
+
+    index = platform_get_snd_device_index((char *)attr[1]);
+    if (index < 0) {
+        ALOGE("%s: Device %s in platform info xml not found, no MODULE ID set!",
+              __func__, attr[1]);
+        goto done;
+    }
+
+    if (strcmp(attr[2], "module_id") != 0) {
+        ALOGE("%s: Device %s in platform info xml has no module_id, no MODULE ID set!",
+              __func__, attr[2]);
+        goto done;
+    }
+
+    if (strcmp(attr[4], "instance_id") != 0) {
+        ALOGE("%s: Device %s in platform info xml has no instance_id, no INSTANCE ID set!",
+              __func__, attr[4]);
+        goto done;
+    }
+
+    if (strcmp(attr[6], "param_id") != 0) {
+        ALOGE("%s: Device %s in platform info xml has no param_id, no PARAM ID set!",
+              __func__, attr[6]);
+        goto done;
+    }
+
+    if (strcmp(attr[8], "param_value") != 0) {
+        ALOGE("%s: Device %s in platform info xml has no param_value, no PARAM VALUE set!",
+              __func__, attr[8]);
+        goto done;
+    }
+
+    effect_config = (struct audio_effect_config){strtol((char *)attr[3], NULL, 0),
+                                                 strtol((char *)attr[5], NULL, 0),
+                                                 strtol((char *)attr[7], NULL, 0),
+                                                 strtol((char *)attr[9], NULL, 0)};
+
+
+    if (platform_set_effect_config_data(index, effect_config, effect_type) < 0) {
+        ALOGE("%s: Effect = %d Device %s, MODULE/INSTANCE/PARAM ID %lu %lu %lu %lu was not set!",
+              __func__, effect_type, attr[1], strtol((char *)attr[3], NULL, 0),
+              strtol((char *)attr[5], NULL, 0), strtol((char *)attr[7], NULL, 0),
+              strtol((char *)attr[9], NULL, 0));
+        goto done;
+    }
+
+done:
+    return;
+}
+
+static void process_effect_aec(const XML_Char **attr)
+{
+    process_audio_effect(attr, EFFECT_AEC);
+    return;
+}
+
+static void process_effect_ns(const XML_Char **attr)
+{
+    process_audio_effect(attr, EFFECT_NS);
+    return;
+}
+
 static void process_bit_width(const XML_Char **attr)
 {
     int index;
@@ -418,6 +502,8 @@
             section = BITWIDTH;
         } else if (strcmp(tag_name, "acdb_ids") == 0) {
             section = ACDB;
+        } else if (strcmp(tag_name, "module_ids") == 0) {
+            section = MODULE;
         } else if (strcmp(tag_name, "pcm_ids") == 0) {
             section = PCM_ID;
         } else if (strcmp(tag_name, "backend_names") == 0) {
@@ -431,7 +517,8 @@
         } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
             section = ACDB_METAINFO_KEY;
         } else if (strcmp(tag_name, "device") == 0) {
-            if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
+            if ((section != ACDB) && (section != AEC) && (section != NS) &&
+                (section != BACKEND_NAME) && (section != BITWIDTH) &&
                 (section != INTERFACE_NAME)) {
                 ALOGE("device tag only supported for acdb/backend names/bitwitdh/interface names");
                 return;
@@ -465,6 +552,20 @@
             section_process_fn fn = section_table[section];
             fn(attr);
         }
+        else if (strcmp(tag_name, "aec") == 0) {
+            if (section != MODULE) {
+                ALOGE("aec tag only supported with MODULE section");
+                return;
+            }
+            section = AEC;
+        }
+        else if (strcmp(tag_name, "ns") == 0) {
+            if (section != MODULE) {
+                ALOGE("ns tag only supported with MODULE section");
+                return;
+            }
+            section = NS;
+        }
     } else {
             ALOGE("%s: unknown caller!", __func__);
     }
@@ -477,6 +578,12 @@
         section = ROOT;
     } else if (strcmp(tag_name, "acdb_ids") == 0) {
         section = ROOT;
+    } else if (strcmp(tag_name, "module_ids") == 0) {
+        section = ROOT;
+    } else if (strcmp(tag_name, "aec") == 0) {
+        section = MODULE;
+    } else if (strcmp(tag_name, "ns") == 0) {
+        section = MODULE;
     } else if (strcmp(tag_name, "pcm_ids") == 0) {
         section = ROOT;
     } else if (strcmp(tag_name, "backend_names") == 0) {
diff --git a/hal/voice.c b/hal/voice.c
index 5a3ff33..b3645be 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -221,6 +221,13 @@
     uc_info->in_snd_device = SND_DEVICE_NONE;
     uc_info->out_snd_device = SND_DEVICE_NONE;
 
+    if (audio_is_bluetooth_sco_device(uc_info->devices) && !adev->bt_sco_on) {
+        ALOGE("start_call: couldn't find BT SCO, SCO is not ready");
+        adev->voice.in_call = false;
+        ret = -EIO;
+        goto error_start_voice;
+    }
+
     list_add_tail(&adev->usecase_list, &uc_info->list);
 
     select_devices(adev, usecase_id);
diff --git a/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h b/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
index 374611a..6041ffe 100644
--- a/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
+++ b/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
@@ -53,6 +53,7 @@
 #include "QOMX_AudioIndexExtensions.h"
 #include "OMX_Core.h"
 #include "OMX_Audio.h"
+#include "OMX_IndexExt.h"
 #include "aenc_svr.h"
 #include "qc_omx_component.h"
 #include "Map.h"
diff --git a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
index ca6bb6e..51b2056 100644
--- a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
+++ b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
@@ -45,6 +45,14 @@
 
 #define SLEEP_MS 100
 
+static const OMX_U32 supported_profiles[] = {
+    OMX_AUDIO_AACObjectLC,
+    OMX_AUDIO_AACObjectHE,
+    OMX_AUDIO_AACObjectHE_PS,
+};
+
+static const int num_profiles = sizeof(supported_profiles) / sizeof(supported_profiles[0]);
+
 // omx_cmd_queue destructor
 omx_aac_aenc::omx_cmd_queue::~omx_cmd_queue()
 {
@@ -2777,6 +2785,25 @@
                 break;
 
             }
+        case OMX_IndexParamAudioProfileQuerySupported:
+        {
+            DEBUG_PRINT("OMX_IndexParamAudioProfileQuerySupported");
+            OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *profileParams =
+                    (OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *)paramData;
+
+            if (profileParams->nPortIndex != 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (profileParams->nProfileIndex >= num_profiles) {
+                return OMX_ErrorNoMore;
+            }
+
+            profileParams->eProfile =
+                    supported_profiles[profileParams->nProfileIndex];
+
+            return OMX_ErrorNone;
+        }
         default:
             {
                 DEBUG_PRINT_ERROR("unknown param %08x\n", paramIndex);
diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h
index c13a1a4..a301bf9 100644
--- a/qahw_api/inc/qahw_defs.h
+++ b/qahw_api/inc/qahw_defs.h
@@ -347,9 +347,9 @@
     uint16_t num_output_channels;
     uint16_t num_input_channels;
     uint8_t has_output_channel_map;
-    uint32_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+    uint16_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
     uint8_t has_input_channel_map;
-    uint32_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+    uint16_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
     uint8_t has_mixer_coeffs;
     float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
 } qahw_mix_matrix_params_t;
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index 1338591..fc55f83 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -162,7 +162,7 @@
 #endif
 
 #ifndef AUDIO_OUTPUT_FLAG_INTERACTIVE
-#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x80000000
+#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x4000000
 #endif
 
 static bool request_wake_lock(bool wakelock_acquired, bool enable)
@@ -1830,7 +1830,7 @@
     return channel_type;
 }
 
-int extract_channel_mapping(uint32_t *channel_map, const char * arg_string){
+int extract_channel_mapping(uint16_t *channel_map, const char * arg_string){
 
     char *token_string = NULL;
     char *init_ptr = NULL;
diff --git a/qahw_api/test/qap_wrapper_extn.c b/qahw_api/test/qap_wrapper_extn.c
index 4c35711..d9f27d4 100644
--- a/qahw_api/test/qap_wrapper_extn.c
+++ b/qahw_api/test/qap_wrapper_extn.c
@@ -62,6 +62,7 @@
 #define DEFAULT_SAMPLE_RATE 48000
 #define MAX_QAP_MODULE_OUT 3
 
+extern bool stop_playback;
 bool is_media_fmt_changed[MAX_QAP_MODULE_OUT];
 int new_output_conf_index = 0;
 
@@ -1491,9 +1492,12 @@
         buffer->common_params.offset = 0;
         buffer->common_params.size = bytes_read;
         memcpy(buffer->common_params.data, data_buf, bytes_read);
-        if (bytes_read <= 0) {
+        if (bytes_read <= 0 || stop_playback) {
             buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_EOS;
             bytes_consumed = qap_module_process(qap_module_handle, buffer);
+            if (stop_playback)
+                qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_FLUSH, sizeof(QAP_MODULE_CMD_FLUSH), NULL, NULL, NULL);
+
             ret = qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_STOP, sizeof(QAP_MODULE_CMD_STOP), NULL, NULL, NULL);
             fprintf(stdout, "Stopped feeding input %s : %p\n", stream_info->filename, fp_input);
             ALOGV("Stopped feeding input %s : %p", stream_info->filename, fp_input);
@@ -1546,7 +1550,7 @@
                     }
                 }
             }
-        } while (buffer->common_params.size > 0);
+        } while (buffer->common_params.size > 0 && !stop_playback);
         if (reply_data)
             free(reply_data);
         buffer->common_params.data = temp_ptr;