Merge "hal: spkr_prot: Update the thermal zone path to physical path"
diff --git a/configs/msm8998/audio_platform_info.xml b/configs/msm8998/audio_platform_info.xml
index 56ac9bb..3e8ff0e 100644
--- a/configs/msm8998/audio_platform_info.xml
+++ b/configs/msm8998/audio_platform_info.xml
@@ -49,7 +49,6 @@
         <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD6" type="out" id="30"/>
         <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD7" type="out" id="31"/>
         <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD8" type="out" id="32"/>
-        <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD9" type="out" id="33"/>
         <usecase name="USECASE_VOICEMMODE1_CALL" type="in" id="2"/>
         <usecase name="USECASE_VOICEMMODE1_CALL" type="out" id="2"/>
         <usecase name="USECASE_VOICEMMODE2_CALL" type="in" id="19"/>
@@ -65,6 +64,8 @@
         <usecase name="USECASE_AUDIO_RECORD_LOW_LATENCY" type="in" id="17" />
         <usecase name="USECASE_AUDIO_PLAYBACK_ULL" type="out" id="17" />
         <usecase name="USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE" type="out" id="27" />
+        <usecase name="USECASE_AUDIO_PLAYBACK_MMAP" type="out" id="33" />
+        <usecase name="USECASE_AUDIO_RECORD_MMAP" type="in" id="33" />
     </pcm_ids>
     <config_params>
         <param key="spkr_1_tz_name" value="wsatz.13"/>
diff --git a/configs/msm8998/audio_policy_configuration.xml b/configs/msm8998/audio_policy_configuration.xml
index 09a4bb9..ff0820e 100644
--- a/configs/msm8998/audio_policy_configuration.xml
+++ b/configs/msm8998/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"
@@ -191,6 +195,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>
@@ -302,15 +311,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"
@@ -318,9 +327,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"
@@ -331,6 +340,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/mixer_paths_tavil.xml b/configs/msm8998/mixer_paths_tavil.xml
index 51a3083..87223d6 100644
--- a/configs/msm8998/mixer_paths_tavil.xml
+++ b/configs/msm8998/mixer_paths_tavil.xml
@@ -297,6 +297,7 @@
     <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia4" value="0" />
     <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia5" value="0" />
     <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia6" value="0" />
+    <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia16" value="0" />
     <ctl name="MultiMedia1 Mixer SLIM_7_TX" value="0" />
     <!-- audio record compress-->
     <ctl name="MultiMedia8 Mixer SLIM_0_TX" value="0" />
@@ -2593,4 +2594,83 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="mmap-playback">
+        <ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback headphones">
+        <ctl name="SLIMBUS_6_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-headphones">
+        <path name="mmap-playback" />
+        <path name="mmap-playback headphones" />
+    </path>
+
+    <path name="mmap-playback bt-sco">
+        <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback bt-sco-wb">
+        <ctl name="BT SampleRate" value="KHZ_16" />
+        <path name="mmap-playback bt-sco" />
+    </path>
+
+    <path name="mmap-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-buffer-playback hdmi">
+        <ctl name="HDMI Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-hdmi">
+        <path name="mmap-playback hdmi" />
+        <path name="mmap-playback" />
+    </path>
+
+    <path name="mmap-playback speaker-and-display-port">
+        <path name="mmap-playback display-port" />
+        <path name="mmap-playback" />
+    </path>
+
+    <path name="mmap-playback speaker-and-usb-headphones">
+        <path name="mmap-playback usb-headphones" />
+        <path name="mmap-playback" />
+    </path>
+
+    <path name="mmap-record">
+      <ctl name="MultiMedia16 Mixer SLIM_0_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco">
+      <ctl name="MultiMedia16 Mixer SLIM_7_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco-wb">
+        <ctl name="BT SampleRate" value="KHZ_16" />
+        <path name="mmap-record bt-sco" />
+    </path>
+
+    <path name="mmap-record capture-fm">
+      <ctl name="MultiMedia16 Mixer SLIM_8_TX" value="1" />
+    </path>
+
+    <path name="mmap-record usb-headset-mic">
+       <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/mixer_paths.xml b/configs/sdm660/mixer_paths.xml
index 75082c7..459ffa1 100644
--- a/configs/sdm660/mixer_paths.xml
+++ b/configs/sdm660/mixer_paths.xml
@@ -67,6 +67,7 @@
     <ctl name="MultiMedia1 Mixer SLIM_7_TX" value="0" />
     <ctl name="MultiMedia8 Mixer INT3_MI2S_TX" value="0" />
     <ctl name="MultiMedia8 Mixer SLIM_7_TX" value="0" />
+    <ctl name="MultiMedia16 Mixer SLIM_7_TX" value="0" />
     <ctl name="HDMI Mixer MultiMedia1" value="0" />
     <ctl name="HDMI Mixer MultiMedia2" value="0" />
     <ctl name="HDMI Mixer MultiMedia3" value="0" />
@@ -2256,4 +2257,59 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="mmap-playback">
+        <ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback headphones">
+        <ctl name="SLIMBUS_6_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-headphones">
+        <path name="mmap-playback" />
+        <path name="mmap-playback headphones" />
+    </path>
+
+    <path name="mmap-playback bt-sco">
+        <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback bt-sco-wb">
+        <ctl name="BT SampleRate" value="16000" />
+        <path name="mmap-playback bt-sco" />
+    </path>
+
+    <path name="mmap-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-record">
+      <ctl name="MultiMedia16 Mixer SLIM_0_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco">
+      <ctl name="MultiMedia16 Mixer SLIM_7_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco-wb">
+        <ctl name="AUX PCM SampleRate" value="16000" />
+        <path name="mmap-record bt-sco" />
+    </path>
+
+    <path name="mmap-record capture-fm">
+      <ctl name="MultiMedia16 Mixer TERT_MI2S_TX" value="1" />
+    </path>
+
+    <path name="mmap-record usb-headset-mic">
+       <ctl name="MultiMedia16 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 98b0733..2dbcd2a 100644
--- a/configs/sdm660/mixer_paths_skus.xml
+++ b/configs/sdm660/mixer_paths_skus.xml
@@ -2516,7 +2516,7 @@
         <ctl name="DMIC MUX7" value="DMIC5" />
         <ctl name="SLIM TX8 MUX" value="DEC8" />
         <ctl name="ADC MUX8" value="DMIC" />
-        <ctl name="DMIC MUX8" value="DMIC1" />
+        <ctl name="DMIC MUX8" value="DMIC5" />
     </path>
 
     <path name="speaker-qmic-liquid">
diff --git a/configs/sdm660/mixer_paths_wcd9335.xml b/configs/sdm660/mixer_paths_wcd9335.xml
index 964c5bc..8cc6f65 100644
--- a/configs/sdm660/mixer_paths_wcd9335.xml
+++ b/configs/sdm660/mixer_paths_wcd9335.xml
@@ -2817,4 +2817,58 @@
         <path name="audio-ull-playback" />
     </path>
 
+    <path name="mmap-playback">
+        <ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback headphones">
+        <ctl name="SLIMBUS_6_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-headphones">
+        <path name="mmap-playback" />
+        <path name="mmap-playback headphones" />
+    </path>
+
+    <path name="mmap-playback bt-sco">
+        <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback bt-sco-wb">
+        <ctl name="BT SampleRate" value="16000" />
+        <path name="mmap-playback bt-sco" />
+    </path>
+
+    <path name="mmap-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-record">
+      <ctl name="MultiMedia16 Mixer SLIM_0_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco">
+      <ctl name="MultiMedia16 Mixer SLIM_7_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco-wb">
+        <ctl name="BT SampleRate" value="KHZ_16" />
+        <path name="mmap-record bt-sco" />
+    </path>
+
+    <path name="mmap-record capture-fm">
+      <ctl name="MultiMedia16 Mixer SLIM_8_TX" value="1" />
+    </path>
+
+    <path name="mmap-record usb-headset-mic">
+       <ctl name="MultiMedia16 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 2b7f422..213f5c3 100644
--- a/configs/sdm660/mixer_paths_wcd9340.xml
+++ b/configs/sdm660/mixer_paths_wcd9340.xml
@@ -2564,4 +2564,59 @@
         <path name="audio-ull-playback" />
     </path>
 
+    <path name="mmap-playback">
+        <ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback headphones">
+        <ctl name="SLIMBUS_6_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-headphones">
+        <path name="mmap-playback" />
+        <path name="mmap-playback headphones" />
+    </path>
+
+    <path name="mmap-playback bt-sco">
+        <ctl name="AUX_PCM_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback bt-sco-wb">
+        <ctl name="AUX PCM SampleRate" value="16000" />
+        <path name="mmap-playback bt-sco" />
+    </path>
+
+    <path name="mmap-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-record">
+      <ctl name="MultiMedia16 Mixer SLIM_0_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco">
+      <ctl name="MultiMedia16 Mixer AUX_PCM_UL_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco-wb">
+        <ctl name="AUX PCM SampleRate" value="16000" />
+        <path name="mmap-record bt-sco" />
+    </path>
+
+    <path name="mmap-record capture-fm">
+      <ctl name="MultiMedia16 Mixer TERT_MI2S_TX" value="1" />
+    </path>
+
+    <path name="mmap-record usb-headset-mic">
+       <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml b/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml
index 691b2e3..0efade0 100644
--- a/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml
+++ b/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml
@@ -36,6 +36,14 @@
     <ctl name="LSM6 Mixer SLIMBUS_5_TX" value="0" />
     <ctl name="LSM7 Mixer SLIMBUS_5_TX" value="0" />
     <ctl name="LSM8 Mixer SLIMBUS_5_TX" value="0" />
+    <ctl name="LSM1 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM2 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM3 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM4 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM5 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM6 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM7 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM8 Mixer SLIMBUS_0_TX" value="0" />
     <ctl name="LSM1 Port" value="None" />
     <ctl name="LSM2 Port" value="None" />
     <ctl name="LSM3 Port" value="None" />
@@ -45,6 +53,7 @@
     <ctl name="LSM7 Port" value="None" />
     <ctl name="LSM8 Port" value="None" />
     <ctl name="SLIMBUS_5_TX LSM Function" value="None" />
+    <ctl name="SLIMBUS_0_TX LSM Function" value="None" />
     <ctl name="MADONOFF Switch" value="0" />
     <ctl name="MAD Input" value="DMIC1" />
     <ctl name="MAD_BROADCAST Switch" value="0" />
@@ -52,10 +61,27 @@
     <ctl name="AIF4_MAD Mixer SLIM TX12" value="0" />
     <ctl name="AIF4_MAD Mixer SLIM TX13" value="0" />
     <ctl name="CPE AFE MAD Enable" value="0"/>
+    <ctl name="AIF1_CAP Mixer SLIM TX8" value="0"/>
+    <ctl name="AIF1_CAP Mixer SLIM TX7" value="0" />
+    <ctl name="AIF1_CAP Mixer SLIM TX6" value="0" />
+    <ctl name="AIF1_CAP Mixer SLIM TX5" value="0"/>
+    <ctl name="SLIM TX5 MUX" value="ZERO" />
+    <ctl name="SLIM TX6 MUX" value="ZERO" />
+    <ctl name="SLIM TX7 MUX" value="ZERO" />
+    <ctl name="SLIM TX8 MUX" value="ZERO" />
+    <ctl name="ADC MUX5" value="AMIC" />
+    <ctl name="ADC MUX6" value="AMIC" />
+    <ctl name="ADC MUX7" value="AMIC" />
+    <ctl name="ADC MUX8" value="AMIC" />
+    <ctl name="DMIC MUX5" value="ZERO" />
+    <ctl name="DMIC MUX6" value="ZERO" />
+    <ctl name="DMIC MUX7" value="ZERO" />
+    <ctl name="DMIC MUX8" value="ZERO" />
     <ctl name="CLK MODE" value="EXTERNAL" />
     <ctl name="EC BUF MUX INP" value="ZERO" />
     <ctl name="ADC MUX1" value="DMIC" />
     <ctl name="DMIC MUX1" value="ZERO" />
+    <ctl name="IIR0 INP0 MUX" value="ZERO" />
 
     <path name="listen-voice-wakeup-1">
         <ctl name="SLIMBUS_5_TX LSM Function" value="AUDIO" />
@@ -99,11 +125,59 @@
         <ctl name="LSM8 Mixer SLIMBUS_5_TX" value="1" />
     </path>
 
+    <path name="listen-voice-wakeup-1 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM1 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM1 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-2 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM2 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM2 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-3 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM3 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM3 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-4 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM4 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM4 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-5 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM5 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM5 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-6 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM6 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM6 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-7 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM7 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM7 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-8 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM8 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM8 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
     <path name="listen-cpe-handset-mic">
         <ctl name="MADONOFF Switch" value="1" />
         <ctl name="TX13 INP MUX" value="CPE_TX_PP" />
         <ctl name="AIF4_MAD Mixer SLIM TX13" value="1" />
-        <ctl name="MAD Input" value="DMIC2" />
+        <ctl name="MAD Input" value="DMIC3" />
         <ctl name="CPE AFE MAD Enable" value="1"/>
     </path>
 
@@ -111,14 +185,14 @@
         <ctl name="CLK MODE" value="INTERNAL" />
         <ctl name="EC BUF MUX INP" value="DEC1" />
         <ctl name="ADC MUX1" value="DMIC" />
-        <ctl name="DMIC MUX1" value="DMIC2" />
+        <ctl name="DMIC MUX1" value="DMIC3" />
     </path>
 
     <!-- path name used for low bandwidth FTRT codec interface -->
     <path name="listen-cpe-handset-mic low-speed-intf">
         <ctl name="MADONOFF Switch" value="1" />
         <ctl name="AIF4_MAD Mixer SLIM TX12" value="1" />
-        <ctl name="MAD Input" value="DMIC2" />
+        <ctl name="MAD Input" value="DMIC3" />
         <ctl name="CPE AFE MAD Enable" value="1"/>
     </path>
 
@@ -126,7 +200,43 @@
         <ctl name="MAD_BROADCAST Switch" value="1" />
         <ctl name="TX13 INP MUX" value="MAD_BRDCST" />
         <ctl name="AIF4_MAD Mixer SLIM TX13" value="1" />
-        <ctl name="MAD Input" value="DMIC2" />
+        <ctl name="MAD Input" value="DMIC3" />
     </path>
 
+    <path name="listen-ape-handset-mic-preproc">
+       <ctl name="AIF1_CAP Mixer SLIM TX7" value="1"/>
+       <ctl name="SLIM_0_TX Channels" value="One" />
+       <ctl name="SLIM TX7 MUX" value="DEC7" />
+       <ctl name="ADC MUX7" value="DMIC" />
+       <ctl name="DMIC MUX7" value="DMIC3" />
+       <ctl name="IIR0 INP0 MUX" value="DEC7" />
+    </path>
+
+    <path name="listen-ape-handset-qmic">
+       <ctl name="AIF1_CAP Mixer SLIM TX5" value="1" />
+       <ctl name="AIF1_CAP Mixer SLIM TX6" value="1" />
+       <ctl name="AIF1_CAP Mixer SLIM TX7" value="1" />
+       <ctl name="AIF1_CAP Mixer SLIM TX8" value="1" />
+       <ctl name="SLIM_0_TX Channels" value="Four" />
+       <ctl name="SLIM TX5 MUX" value="DEC5" />
+       <ctl name="ADC MUX5" value="DMIC" />
+       <ctl name="DMIC MUX5" value="DMIC0" />
+       <ctl name="SLIM TX6 MUX" value="DEC6" />
+       <ctl name="ADC MUX6" value="DMIC" />
+       <ctl name="DMIC MUX6" value="DMIC3" />
+       <ctl name="SLIM TX7 MUX" value="DEC7" />
+       <ctl name="ADC MUX7" value="DMIC" />
+       <ctl name="DMIC MUX7" value="DMIC5" />
+       <ctl name="SLIM TX8 MUX" value="DEC8" />
+       <ctl name="ADC MUX8" value="DMIC" />
+       <ctl name="DMIC MUX8" value="DMIC5" />
+   </path>
+
+   <path name="echo-reference">
+        <ctl name="AUDIO_REF_EC_UL1 MUX" value="SLIM_RX"/>
+        <ctl name="EC Reference Channels" value="One"/>
+        <ctl name="EC Reference Bit Format" value="S16_LE"/>
+        <ctl name="EC Reference SampleRate" value="48000"/>
+   </path>
+
 </mixer>
diff --git a/configs/sdm845/audio_platform_info.xml b/configs/sdm845/audio_platform_info.xml
index abbb294..2ebf284 100644
--- a/configs/sdm845/audio_platform_info.xml
+++ b/configs/sdm845/audio_platform_info.xml
@@ -49,7 +49,6 @@
         <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD6" type="out" id="30"/>
         <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD7" type="out" id="31"/>
         <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD8" type="out" id="32"/>
-        <usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD9" type="out" id="33"/>
         <usecase name="USECASE_VOICEMMODE1_CALL" type="in" id="2"/>
         <usecase name="USECASE_VOICEMMODE1_CALL" type="out" id="2"/>
         <usecase name="USECASE_VOICEMMODE2_CALL" type="in" id="19"/>
@@ -67,6 +66,8 @@
         <usecase name="USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE" type="out" id="27" />
         <usecase name="USECASE_AUDIO_PLAYBACK_VOIP" type="out" id="16" />
         <usecase name="USECASE_AUDIO_RECORD_VOIP" type="in" id="16" />
+        <usecase name="USECASE_AUDIO_PLAYBACK_MMAP" type="out" id="33" />
+        <usecase name="USECASE_AUDIO_RECORD_MMAP" type="in" id="33" />
     </pcm_ids>
     <config_params>
         <param key="spkr_1_tz_name" value="wsatz.13"/>
diff --git a/configs/sdm845/audio_policy_configuration.xml b/configs/sdm845/audio_policy_configuration.xml
index 09a4bb9..655919b 100644
--- a/configs/sdm845/audio_policy_configuration.xml
+++ b/configs/sdm845/audio_policy_configuration.xml
@@ -73,6 +73,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="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 +195,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>
@@ -302,15 +311,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"
@@ -320,7 +329,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,mmap_no_irq_out"/>
                 <route type="mix" sink="Telephony Tx"
                        sources="voice_tx"/>
                 <route type="mix" sink="voice_rx"
@@ -331,6 +340,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/sdm845/mixer_paths_tavil.xml b/configs/sdm845/mixer_paths_tavil.xml
index 41d980b..dda402f 100644
--- a/configs/sdm845/mixer_paths_tavil.xml
+++ b/configs/sdm845/mixer_paths_tavil.xml
@@ -2454,4 +2454,83 @@
         <path name="audio-ull-playback bt-a2dp" />
         <path name="audio-ull-playback" />
     </path>
+
+    <path name="mmap-playback">
+        <ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback headphones">
+        <ctl name="SLIMBUS_6_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-headphones">
+        <path name="mmap-playback" />
+        <path name="mmap-playback headphones" />
+    </path>
+
+    <path name="mmap-playback bt-sco">
+        <ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback bt-sco-wb">
+        <ctl name="BT SampleRate" value="16000" />
+        <path name="mmap-playback bt-sco" />
+    </path>
+
+    <path name="mmap-playback afe-proxy">
+        <ctl name="AFE_PCM_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headphones">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback usb-headset">
+        <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback display-port">
+        <ctl name="DISPLAY_PORT Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-buffer-playback hdmi">
+        <ctl name="HDMI Mixer MultiMedia16" value="1" />
+    </path>
+
+    <path name="mmap-playback speaker-and-hdmi">
+        <path name="mmap-playback hdmi" />
+        <path name="mmap-playback" />
+    </path>
+
+    <path name="mmap-playback speaker-and-display-port">
+        <path name="mmap-playback display-port" />
+        <path name="mmap-playback" />
+    </path>
+
+    <path name="mmap-playback speaker-and-usb-headphones">
+        <path name="mmap-playback usb-headphones" />
+        <path name="mmap-playback" />
+    </path>
+
+    <path name="mmap-record">
+      <ctl name="MultiMedia16 Mixer SLIM_0_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco">
+      <ctl name="MultiMedia16 Mixer SLIM_7_TX" value="1" />
+    </path>
+
+    <path name="mmap-record bt-sco-wb">
+        <ctl name="BT SampleRate" value="KHZ_16" />
+        <path name="mmap-record bt-sco" />
+    </path>
+
+    <path name="mmap-record capture-fm">
+      <ctl name="MultiMedia16 Mixer SLIM_8_TX" value="1" />
+    </path>
+
+    <path name="mmap-record usb-headset-mic">
+       <ctl name="MultiMedia16 Mixer USB_AUDIO_TX" value="1" />
+    </path>
+
 </mixer>
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index b96a147..2103930 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -55,6 +55,7 @@
 #define ENC_MEDIA_FMT_APTX                                 0x000131ff
 #define ENC_MEDIA_FMT_APTX_HD                              0x00013200
 #define ENC_MEDIA_FMT_SBC                                  0x00010BF2
+#define ENC_MEDIA_FMT_CELT                                 0x00013221
 #define MEDIA_FMT_AAC_AOT_LC                               2
 #define MEDIA_FMT_AAC_AOT_SBR                              5
 #define MEDIA_FMT_AAC_AOT_PS                               29
@@ -78,10 +79,29 @@
 #define ENCODER_LATENCY_APTX       40
 #define ENCODER_LATENCY_APTX_HD    20
 #define ENCODER_LATENCY_AAC        70
+//To Do: Fine Tune Encoder CELT latency.
+#define ENCODER_LATENCY_CELT       40
 #define DEFAULT_SINK_LATENCY_SBC       140
 #define DEFAULT_SINK_LATENCY_APTX      160
 #define DEFAULT_SINK_LATENCY_APTX_HD   180
 #define DEFAULT_SINK_LATENCY_AAC       180
+//To Do: Fine Tune Default CELT Latency.
+#define DEFAULT_SINK_LATENCY_CELT      180
+
+/*
+ * Below enum values are extended from audio_base.h to
+ * to keep encoder codec type local to bthost_ipc
+ * and audio_hal as these are intended only for handshake
+ * between IPC lib and Audio HAL.
+ */
+typedef enum {
+    ENC_CODEC_TYPE_INVALID = 4294967295u, // 0xFFFFFFFFUL
+    ENC_CODEC_TYPE_AAC = 67108864u, // 0x04000000UL
+    ENC_CODEC_TYPE_SBC = 520093696u, // 0x1F000000UL
+    ENC_CODEC_TYPE_APTX = 536870912u, // 0x20000000UL
+    ENC_CODEC_TYPE_APTX_HD = 553648128u, // 0x21000000UL
+    ENC_CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
+}enc_codec_t;
 
 typedef int (*audio_stream_open_t)(void);
 typedef int (*audio_stream_close_t)(void);
@@ -91,7 +111,7 @@
 typedef void (*audio_handoff_triggered_t)(void);
 typedef void (*clear_a2dpsuspend_flag_t)(void);
 typedef void * (*audio_get_codec_config_t)(uint8_t *multicast_status,uint8_t *num_dev,
-                               audio_format_t *codec_type);
+                               enc_codec_t *codec_type);
 typedef int (*audio_check_a2dp_ready_t)(void);
 typedef uint16_t (*audio_get_a2dp_sink_latency_t)(void);
 
@@ -120,7 +140,7 @@
     audio_check_a2dp_ready_t audio_check_a2dp_ready;
     audio_get_a2dp_sink_latency_t audio_get_a2dp_sink_latency;
     enum A2DP_STATE bt_state;
-    audio_format_t bt_encoder_format;
+    enc_codec_t bt_encoder_format;
     uint32_t enc_sampling_rate;
     bool a2dp_started;
     bool a2dp_suspended;
@@ -177,7 +197,7 @@
  * 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_aptx_t
+struct custom_enc_cfg_t
 {
     uint32_t      enc_format;
     uint32_t      sample_rate;
@@ -187,20 +207,35 @@
     uint32_t      custom_size;
 };
 
+struct celt_specific_enc_cfg_t
+{
+    uint32_t      bit_rate;
+    uint16_t      frame_size;
+    uint16_t      complexity;
+    uint16_t      prediction_mode;
+    uint16_t      vbr_flag;
+};
+
+struct celt_enc_cfg_t
+{
+    struct custom_enc_cfg_t  custom_cfg;
+    struct celt_specific_enc_cfg_t celt_cfg;
+};
+
 /* TODO: Define the following structures only for O using PLATFORM_VERSION */
 /* Information about BT SBC encoder configuration
  * This data is used between audio HAL module and
  * BT IPC library to configure DSP encoder
  */
 typedef struct {
-    uint32_t subband;    /* 4, 8 */
-    uint32_t blk_len;    /* 4, 8, 12, 16 */
-    uint16_t sampling_rate; /*44.1khz,48khz*/
-    uint8_t  channels;      /*0(Mono),1(Dual_mono),2(Stereo),3(JS)*/
-    uint8_t  alloc;         /*0(Loudness),1(SNR)*/
-    uint8_t  min_bitpool;   /* 2 */
-    uint8_t  max_bitpool;   /*53(44.1khz),51 (48khz) */
-    uint32_t bitrate;      /* 320kbps to 512kbps */
+    uint32_t subband;        /* 4, 8 */
+    uint32_t blk_len;        /* 4, 8, 12, 16 */
+    uint16_t sampling_rate;  /*44.1khz,48khz*/
+    uint8_t  channels;       /*0(Mono),1(Dual_mono),2(Stereo),3(JS)*/
+    uint8_t  alloc;          /*0(Loudness),1(SNR)*/
+    uint8_t  min_bitpool;    /* 2 */
+    uint8_t  max_bitpool;    /*53(44.1khz),51 (48khz) */
+    uint32_t bitrate;        /* 320kbps to 512kbps */
 } audio_sbc_encoder_config;
 
 
@@ -227,6 +262,20 @@
     uint32_t bitrate;
 } audio_aac_encoder_config;
 
+/* Information about BT CELT encoder configuration
+ * This data is used between audio HAL module and
+ * BT IPC library to configure DSP encoder
+ */
+typedef struct {
+    uint32_t sampling_rate; /* 32000 - 48000, 48000 */
+    uint16_t channels; /* 1-Mono, 2-Stereo, 2*/
+    uint16_t frame_size; /* 64-128-256-512, 512 */
+    uint16_t complexity; /* 0-10, 1 */
+    uint16_t prediction_mode; /* 0-1-2, 0 */
+    uint16_t vbr_flag; /* 0-1, 0*/
+    uint32_t bitrate; /*32000 - 1536000, 139500*/
+} audio_celt_encoder_config;
+
 /*********** END of DSP configurable structures ********************/
 
 /* API to identify DSP encoder captabilities */
@@ -252,6 +301,10 @@
             ALOGD("%s: aac offload supported\n",__func__);
             a2dp.is_a2dp_offload_supported = true;
             break;
+        } else if (strcmp(tok, "celt") == 0) {
+            ALOGD("%s: celt offload supported\n",__func__);
+            a2dp.is_a2dp_offload_supported = true;
+            break;
         }
         tok = strtok_r(NULL, "-", &saveptr);
     };
@@ -348,7 +401,7 @@
     a2dp.a2dp_started = false;
     a2dp.a2dp_total_active_session_request = 0;
     a2dp.a2dp_suspended = false;
-    a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_INVALID;
     a2dp.enc_sampling_rate = 48000;
     a2dp.bt_state = A2DP_STATE_DISCONNECTED;
 
@@ -372,7 +425,6 @@
         is_configured = false;
         goto fail;
     }
-    a2dp.bt_encoder_format = AUDIO_FORMAT_SBC;
     memset(&sbc_dsp_cfg, 0x0, sizeof(struct sbc_enc_cfg_t));
     sbc_dsp_cfg.enc_format = ENC_MEDIA_FMT_SBC;
     sbc_dsp_cfg.num_subbands = sbc_bt_cfg->subband;
@@ -419,6 +471,7 @@
         goto fail;
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_SBC;
     a2dp.enc_sampling_rate = sbc_bt_cfg->sampling_rate;
     ALOGV("Successfully updated SBC enc format with samplingrate: %d channelmode:%d",
            sbc_dsp_cfg.sample_rate, sbc_dsp_cfg.channel_mode);
@@ -430,7 +483,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_aptx_t aptx_dsp_cfg;
+    struct custom_enc_cfg_t aptx_dsp_cfg;
     bool is_configured = false;
     int ret = 0;
 
@@ -443,8 +496,7 @@
         is_configured = false;
         goto fail;
     }
-    a2dp.bt_encoder_format = AUDIO_FORMAT_APTX;
-    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
+    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;
@@ -459,7 +511,7 @@
             break;
     }
     ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
-                              sizeof(struct custom_enc_cfg_aptx_t));
+                              sizeof(struct custom_enc_cfg_t));
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX encoder config", __func__);
         is_configured = false;
@@ -480,6 +532,7 @@
         }
     }
     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);
@@ -492,7 +545,7 @@
 bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
-    struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
+    struct custom_enc_cfg_t aptx_dsp_cfg;
     bool is_configured = false;
     int ret = 0;
 
@@ -506,8 +559,7 @@
         goto fail;
     }
 
-    a2dp.bt_encoder_format = AUDIO_FORMAT_APTX_HD;
-    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
+    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_t));
     aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX_HD;
     aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
     aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
@@ -522,7 +574,7 @@
             break;
     }
     ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
-                              sizeof(struct custom_enc_cfg_aptx_t));
+                              sizeof(struct custom_enc_cfg_t));
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX HD encoder config", __func__);
         is_configured = false;
@@ -541,6 +593,7 @@
         goto fail;
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX_HD;
     a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
     ALOGV("Successfully updated APTX HD encformat with samplingrate: %d channels:%d",
            aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
@@ -565,7 +618,6 @@
         is_configured = false;
         goto fail;
     }
-    a2dp.bt_encoder_format = AUDIO_FORMAT_AAC;
     memset(&aac_dsp_cfg, 0x0, sizeof(struct aac_enc_cfg_t));
     aac_dsp_cfg.enc_format = ENC_MEDIA_FMT_AAC;
     aac_dsp_cfg.bit_rate = aac_bt_cfg->bitrate;
@@ -605,6 +657,7 @@
         goto fail;
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_AAC;
     a2dp.enc_sampling_rate = aac_bt_cfg->sampling_rate;
     ALOGV("Successfully updated AAC enc format with samplingrate: %d channels:%d",
            aac_dsp_cfg.sample_rate, aac_dsp_cfg.channel_cfg);
@@ -612,11 +665,77 @@
     return is_configured;
 }
 
+bool configure_celt_enc_format(audio_celt_encoder_config *celt_bt_cfg)
+{
+    struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
+    struct celt_enc_cfg_t celt_dsp_cfg;
+    bool is_configured = false;
+    int ret = 0;
+    if(celt_bt_cfg == NULL)
+        return false;
+
+    ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
+    if (!ctl_enc_data) {
+        ALOGE(" ERROR  a2dp encoder CONFIG data mixer control not identifed");
+        is_configured = false;
+        goto fail;
+    }
+    memset(&celt_dsp_cfg, 0x0, sizeof(struct celt_enc_cfg_t));
+
+    celt_dsp_cfg.custom_cfg.enc_format = ENC_MEDIA_FMT_CELT;
+    celt_dsp_cfg.custom_cfg.sample_rate = celt_bt_cfg->sampling_rate;
+    celt_dsp_cfg.custom_cfg.num_channels = celt_bt_cfg->channels;
+    switch(celt_dsp_cfg.custom_cfg.num_channels) {
+        case 1:
+            celt_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_C;
+            break;
+        case 2:
+        default:
+            celt_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+            celt_dsp_cfg.custom_cfg.channel_mapping[1] = PCM_CHANNEL_R;
+            break;
+    }
+
+    celt_dsp_cfg.custom_cfg.custom_size = sizeof(struct celt_enc_cfg_t);
+
+    celt_dsp_cfg.celt_cfg.frame_size = celt_bt_cfg->frame_size;
+    celt_dsp_cfg.celt_cfg.complexity = celt_bt_cfg->complexity;
+    celt_dsp_cfg.celt_cfg.prediction_mode = celt_bt_cfg->prediction_mode;
+    celt_dsp_cfg.celt_cfg.vbr_flag = celt_bt_cfg->vbr_flag;
+    celt_dsp_cfg.celt_cfg.bit_rate = celt_bt_cfg->bitrate;
+
+    ret = mixer_ctl_set_array(ctl_enc_data, (void *)&celt_dsp_cfg,
+                              sizeof(struct celt_enc_cfg_t));
+    if (ret != 0) {
+        ALOGE("%s: Failed to set CELT encoder config", __func__);
+        is_configured = false;
+        goto fail;
+    }
+    ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_BIT_FORMAT);
+    if (!ctrl_bit_format) {
+        ALOGE(" ERROR  bit format CONFIG data mixer control not identifed");
+        is_configured = false;
+        goto fail;
+    }
+    ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+    if (ret != 0) {
+        ALOGE("%s: Failed to set bit format to encoder", __func__);
+        is_configured = false;
+        goto fail;
+    }
+    is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_CELT;
+    a2dp.enc_sampling_rate = celt_bt_cfg->sampling_rate;
+    ALOGV("Successfully updated CELT encformat with samplingrate: %d channels:%d",
+           celt_dsp_cfg.custom_cfg.sample_rate, celt_dsp_cfg.custom_cfg.num_channels);
+fail:
+    return is_configured;
+}
 bool configure_a2dp_encoder_format()
 {
     void *codec_info = NULL;
     uint8_t multi_cast = 0, num_dev = 1;
-    audio_format_t codec_type = AUDIO_FORMAT_INVALID;
+    enc_codec_t codec_type = ENC_CODEC_TYPE_INVALID;
     bool is_configured = false;
 
     if (!a2dp.audio_get_codec_config) {
@@ -628,26 +747,31 @@
                                &codec_type);
 
     switch(codec_type) {
-        case AUDIO_FORMAT_SBC:
+        case ENC_CODEC_TYPE_SBC:
             ALOGD(" Received SBC encoder supported BT device");
             is_configured =
                configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
             break;
-        case AUDIO_FORMAT_APTX:
+        case ENC_CODEC_TYPE_APTX:
             ALOGD(" Received APTX encoder supported BT device");
             is_configured =
               configure_aptx_enc_format((audio_aptx_encoder_config *)codec_info);
             break;
-        case AUDIO_FORMAT_APTX_HD:
+        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);
             break;
-        case AUDIO_FORMAT_AAC:
+        case ENC_CODEC_TYPE_AAC:
             ALOGD(" Received AAC encoder supported BT device");
             is_configured =
               configure_aac_enc_format((audio_aac_encoder_config *)codec_info);
             break;
+        case ENC_CODEC_TYPE_CELT:
+            ALOGD(" Received CELT encoder supported BT device");
+            is_configured =
+              configure_celt_enc_format((audio_celt_encoder_config *)codec_info);
+            break;
         default:
             ALOGD(" Received Unsupported encoder formar");
             is_configured = false;
@@ -805,7 +929,8 @@
                 a2dp.a2dp_suspended = true;
                 list_for_each(node, &a2dp.adev->usecase_list) {
                     uc_info = node_to_item(node, struct audio_usecase, list);
-                    if (uc_info->type == PCM_PLAYBACK) {
+                    if (uc_info->type == PCM_PLAYBACK &&
+                         (uc_info->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
                         pthread_mutex_unlock(&a2dp.adev->lock);
                         check_a2dp_restore(a2dp.adev, uc_info->stream.out, false);
                         pthread_mutex_lock(&a2dp.adev->lock);
@@ -844,7 +969,8 @@
                 }
                 list_for_each(node, &a2dp.adev->usecase_list) {
                     uc_info = node_to_item(node, struct audio_usecase, list);
-                    if (uc_info->type == PCM_PLAYBACK) {
+                    if (uc_info->type == PCM_PLAYBACK &&
+                         (uc_info->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
                         pthread_mutex_unlock(&a2dp.adev->lock);
                         check_a2dp_restore(a2dp.adev, uc_info->stream.out, true);
                         pthread_mutex_lock(&a2dp.adev->lock);
@@ -874,7 +1000,7 @@
 void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
                                         uint32_t *bit_width)
 {
-    if(a2dp.bt_encoder_format == AUDIO_FORMAT_APTX_HD)
+    if(a2dp.bt_encoder_format == ENC_CODEC_TYPE_APTX_HD)
         *bit_width = 24;
     else
         *bit_width = 16;
@@ -908,7 +1034,7 @@
   a2dp.bt_state = A2DP_STATE_DISCONNECTED;
   a2dp.a2dp_total_active_session_request = 0;
   a2dp.a2dp_suspended = false;
-  a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
+  a2dp.bt_encoder_format = ENC_CODEC_TYPE_INVALID;
   a2dp.enc_sampling_rate = 48000;
   a2dp.is_a2dp_offload_supported = false;
   a2dp.is_handoff_in_progress = false;
@@ -919,14 +1045,14 @@
 {
     uint32_t latency = 0;
     int avsync_runtime_prop = 0;
-    int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0, aac_offset = 0;
+    int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0, aac_offset = 0, celt_offset = 0;
     char value[PROPERTY_VALUE_MAX];
 
     memset(value, '\0', sizeof(char)*PROPERTY_VALUE_MAX);
     avsync_runtime_prop = property_get("vendor.audio.a2dp.codec.latency", value, NULL);
     if (avsync_runtime_prop > 0) {
-        if (sscanf(value, "%d/%d/%d/%d",
-                  &sbc_offset, &aptx_offset, &aptxhd_offset, &aac_offset) != 4) {
+        if (sscanf(value, "%d/%d/%d/%d/%d",
+                  &sbc_offset, &aptx_offset, &aptxhd_offset, &aac_offset, &celt_offset) != 5) {
             ALOGI("Failed to parse avsync offset params from '%s'.", value);
             avsync_runtime_prop = 0;
         }
@@ -938,22 +1064,26 @@
     }
 
     switch(a2dp.bt_encoder_format) {
-        case AUDIO_FORMAT_SBC:
+        case ENC_CODEC_TYPE_SBC:
             latency = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_SBC : slatency;
             break;
-        case AUDIO_FORMAT_APTX:
+        case ENC_CODEC_TYPE_APTX:
             latency = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_APTX : slatency;
             break;
-        case AUDIO_FORMAT_APTX_HD:
+        case ENC_CODEC_TYPE_APTX_HD:
             latency = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_APTX_HD : slatency;
             break;
-        case AUDIO_FORMAT_AAC:
+        case ENC_CODEC_TYPE_AAC:
             latency = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_AAC : slatency;
             break;
+        case ENC_CODEC_TYPE_CELT:
+            latency = (avsync_runtime_prop > 0) ? celt_offset : ENCODER_LATENCY_CELT;
+            latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_CELT : slatency;
+            break;
         default:
             latency = 200;
             break;
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index dfe8c61..4e5f4d8 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -236,6 +236,17 @@
    struct audio_device_cfg_param dev_cfg_params;
 };
 
+typedef struct mix_matrix_params {
+    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];
+    uint8_t has_input_channel_map;
+    uint32_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+    uint8_t has_mixer_coeffs;
+    float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
+} mix_matrix_params_t;
+
 typedef union {
     struct source_tracking_param st_params;
     struct sound_focus_param sf_params;
@@ -248,6 +259,7 @@
     struct audio_adsp_event adsp_event_params;
     struct audio_out_channel_map_param channel_map_param;
     struct audio_device_cfg_param device_cfg;
+    struct mix_matrix_params mm_params;
 } audio_extn_param_payload;
 
 typedef enum {
@@ -264,7 +276,11 @@
     AUDIO_EXTN_PARAM_ADSP_STREAM_CMD,
     /* param to set input channel map for playback stream */
     AUDIO_EXTN_PARAM_OUT_CHANNEL_MAP,
-    AUDIO_EXTN_PARAM_DEVICE_CONFIG
+    AUDIO_EXTN_PARAM_DEVICE_CONFIG,
+    /* Pan/scale params to be set on ASM */
+    AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS,
+    /* Downmix params to be set on ADM */
+    AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS
 } audio_extn_param_id;
 
 #endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 804027b..84de66f 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -1161,6 +1161,7 @@
                                                        "perf_lock_acq");
             if (perf_lock_acq == NULL) {
                 ALOGE("%s: Perf lock Acquire NULL \n", __func__);
+                dlclose(qcopt_handle);
                 ret = -EINVAL;
                 goto err;
             }
@@ -1168,6 +1169,7 @@
                                                        "perf_lock_rel");
             if (perf_lock_rel == NULL) {
                 ALOGE("%s: Perf lock Release NULL \n", __func__);
+                dlclose(qcopt_handle);
                 ret = -EINVAL;
                 goto err;
             }
@@ -1377,6 +1379,14 @@
             ret = audio_extn_utils_set_channel_map(out,
                     (struct audio_out_channel_map_param *)(payload));
             break;
+        case AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS:
+            ret = audio_extn_utils_set_pan_scale_params(out,
+                    (struct mix_matrix_params *)(payload));
+            break;
+        case AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS:
+            ret = audio_extn_utils_set_downmix_params(out,
+                    (struct mix_matrix_params *)(payload));
+            break;
         default:
             ALOGE("%s:: unsupported param_id %d", __func__, param_id);
             break;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index c2a5484..5707742 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -103,6 +103,10 @@
 #define AUDIO_OUTPUT_FLAG_TIMESTAMP 0x10000
 #endif
 
+#ifndef AUDIO_OUTPUT_FLAG_INTERACTIVE
+#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x40000
+#endif
+
 #ifndef COMPRESS_METADATA_NEEDED
 #define audio_extn_parse_compress_metadata(out, parms) (0)
 #else
@@ -599,6 +603,7 @@
                                   struct audio_device *adev,
                                   struct audio_usecase *usecase);
 int audio_extn_utils_get_snd_card_num();
+bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags);
 
 #ifdef DS2_DOLBY_DAP_ENABLED
 #define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
@@ -892,6 +897,12 @@
 int audio_extn_utils_set_channel_map(
             struct stream_out *out,
             struct audio_out_channel_map_param *channel_map_param);
+int audio_extn_utils_set_pan_scale_params(
+            struct stream_out *out,
+            struct mix_matrix_params *mm_params);
+int audio_extn_utils_set_downmix_params(
+            struct stream_out *out,
+            struct mix_matrix_params *mm_params);
 #ifdef AUDIO_HW_LOOPBACK_ENABLED
 /* API to create audio patch */
 int audio_extn_hw_loopback_create_audio_patch(struct audio_hw_device *dev,
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 6da9313..180e575 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -270,7 +270,7 @@
 
     adev->active_input = get_next_active_input(adev);
 
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format) && inout->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false) && inout->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_close(inout->ip_hdlr_handle, true, inout);
         if (ret < 0)
             ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
@@ -284,7 +284,7 @@
         inout->adsp_hdlr_stream_handle = NULL;
     }
 
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format) &&
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false) &&
         inout->ip_hdlr_handle) {
         audio_extn_ip_hdlr_intf_deinit(inout->ip_hdlr_handle);
         inout->ip_hdlr_handle = NULL;
@@ -381,7 +381,7 @@
         inout->adsp_hdlr_stream_handle = NULL;
         goto exit;
     }
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format)) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false)) {
         ret = audio_extn_ip_hdlr_intf_init(&inout->ip_hdlr_handle, NULL, NULL);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d", __func__, ret);
@@ -467,7 +467,7 @@
         ret = -EINVAL;
         goto exit;
     }
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format) && inout->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false) && inout->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_open(inout->ip_hdlr_handle, true, inout,
                                            USECASE_AUDIO_TRANSCODE_LOOPBACK);
         if (ret < 0) {
diff --git a/hal/audio_extn/ip_hdlr_intf.c b/hal/audio_extn/ip_hdlr_intf.c
index 21d4e07..0f31f21 100644
--- a/hal/audio_extn/ip_hdlr_intf.c
+++ b/hal/audio_extn/ip_hdlr_intf.c
@@ -116,10 +116,10 @@
     uint8_t payload[0];
 };
 
-bool audio_extn_ip_hdlr_intf_supported(audio_format_t format)
+bool audio_extn_ip_hdlr_intf_supported(audio_format_t format,bool is_direct_passthru)
 {
     if (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_DOLBY_TRUEHD) ||
-        ((!property_get_bool("audio.offload.passthrough", false)) &&
+        ((!is_direct_passthru) &&
          (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3) ||
          ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3))))
         return true;
diff --git a/hal/audio_extn/ip_hdlr_intf.h b/hal/audio_extn/ip_hdlr_intf.h
index e8a9166..1f2c304 100644
--- a/hal/audio_extn/ip_hdlr_intf.h
+++ b/hal/audio_extn/ip_hdlr_intf.h
@@ -37,7 +37,7 @@
 int audio_extn_ip_hdlr_intf_close(void *handle, bool is_dsp_decode, void *aud_sess_handle);
 int audio_extn_ip_hdlr_intf_init(void **handle, char *lib_path, void **lib_handle);
 int audio_extn_ip_hdlr_intf_deinit(void *handle);
-bool audio_extn_ip_hdlr_intf_supported(audio_format_t format);
+bool audio_extn_ip_hdlr_intf_supported(audio_format_t format, bool is_direct_passthru);
 
 #else
 
@@ -45,7 +45,7 @@
 #define audio_extn_ip_hdlr_intf_close(handle, is_dsp_decode, aud_sess_handle) (0)
 #define audio_extn_ip_hdlr_intf_init(handle, lib_path, lib_handle)            (0)
 #define audio_extn_ip_hdlr_intf_deinit(handle)                                (0)
-#define audio_extn_ip_hdlr_intf_supported(format)                             (0)
+#define audio_extn_ip_hdlr_intf_supported(format, is_direct_passthru)                             (0)
 
 #endif
 
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index 31c94f6..ee9995c 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -417,6 +417,19 @@
 
 }
 
+bool audio_extn_passthru_is_direct_passthrough(struct stream_out *out)
+{
+    //check passthrough system property
+    if (!property_get_bool("audio.offload.passthrough", false)) {
+        return false;
+    }
+
+    if ((out != NULL) && (out->compr_config.codec->compr_passthr == PASSTHROUGH || out->compr_config.codec->compr_passthr == PASSTHROUGH_IEC61937))
+        return true;
+    else
+        return false;
+}
+
 bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out)
 {
     //check passthrough system property
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 9f78a0c..48d20ee 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -102,6 +102,10 @@
 /* ToDo: Check and update a proper value in msec */
 #define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
 
+#ifndef MAX_CHANNELS_SUPPORTED
+#define MAX_CHANNELS_SUPPORTED 8
+#endif
+
 struct string_to_enum {
     const char *name;
     uint32_t value;
@@ -122,6 +126,7 @@
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TIMESTAMP),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INTERACTIVE),
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_NONE),
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
@@ -388,6 +393,7 @@
     struct mixer_ctl *ctl = NULL;
     const char *mixer_ctl_name = "App Type Config";
     struct streams_io_cfg *s_info = NULL;
+    uint32_t target_bit_width = 0;
 
     if (!mixer) {
         ALOGE("%s: mixer is null",__func__);
@@ -413,6 +419,9 @@
         num_app_types += 1;
     }
 
+    /* get target bit width for ADM enforce mode */
+    target_bit_width = adev_get_dsp_bit_width_enforce_mode();
+
     list_for_each(node, streams_output_cfg_list) {
         s_info = node_to_item(node, struct streams_io_cfg, list);
         update = true;
@@ -424,6 +433,11 @@
                     app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
                 if (app_type_cfg[i+3] < (size_t)s_info->app_type_cfg.bit_width)
                     app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
+                /* ADM bit width = max(enforce_bit_width, bit_width from s_info */
+                if (audio_extn_is_dsp_bit_width_enforce_mode_supported(s_info->flags.out_flags) &&
+                    (target_bit_width > app_type_cfg[i+3]))
+                    app_type_cfg[i+3] = target_bit_width;
+
                 update = false;
                 break;
             }
@@ -432,7 +446,12 @@
             num_app_types += 1;
             app_type_cfg[length++] = s_info->app_type_cfg.app_type;
             app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
-            app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
+            app_type_cfg[length] = s_info->app_type_cfg.bit_width;
+            if (audio_extn_is_dsp_bit_width_enforce_mode_supported(s_info->flags.out_flags) &&
+                (target_bit_width > app_type_cfg[length]))
+                app_type_cfg[length] = target_bit_width;
+
+            length++;
         }
     }
     list_for_each(node, streams_input_cfg_list) {
@@ -762,6 +781,28 @@
     return native_usecase;
 }
 
+bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags)
+{
+    /* DSP bitwidth enforce mode for ADM and AFE:
+    * includes:
+    *     deep buffer, low latency, direct pcm and offload.
+    * excludes:
+    *     ull(raw+fast), VOIP.
+    */
+    if ((flags & AUDIO_OUTPUT_FLAG_VOIP_RX) ||
+            ((flags & AUDIO_OUTPUT_FLAG_RAW) &&
+            (flags & AUDIO_OUTPUT_FLAG_FAST)))
+        return false;
+
+
+    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
+            (flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
+            (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) ||
+            (flags & AUDIO_OUTPUT_FLAG_PRIMARY))
+        return true;
+    else
+        return false;
+}
 
 static inline bool audio_is_vr_mode_on(struct audio_device *(__attribute__((unused)) adev))
 {
@@ -821,6 +862,9 @@
     int snd_device = split_snd_device, snd_device_be_idx = -1;
     int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
     char value[PROPERTY_VALUE_MAX] = {0};
+    struct streams_io_cfg *s_info = NULL;
+    struct listnode *node = NULL;
+    int direct_app_type = 0;
 
     ALOGV("%s: usecase->out_snd_device %s, usecase->in_snd_device %s, split_snd_device %s",
           __func__, platform_get_snd_device_name(usecase->out_snd_device),
@@ -837,6 +881,7 @@
         (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_ULL) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_VOIP) &&
+        (!is_interactive_usecase(usecase->id)) &&
         (!is_offload_usecase(usecase->id)) &&
         (usecase->type != PCM_CAPTURE)) {
         ALOGV("%s: a rx/tx/loopback path where app type cfg is not required %d", __func__, usecase->id);
@@ -917,7 +962,18 @@
         }
         sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
 
-        app_type = usecase->stream.out->app_type_cfg.app_type;
+        /* Interactive streams are supported with only direct app type id.
+         * Get Direct profile app type and use it for interactive streams
+         */
+        list_for_each(node, &adev->streams_output_cfg_list) {
+            s_info = node_to_item(node, struct streams_io_cfg, list);
+            if (s_info->flags.out_flags == AUDIO_OUTPUT_FLAG_DIRECT)
+                direct_app_type = s_info->app_type_cfg.app_type;
+        }
+        if (usecase->stream.out->flags == AUDIO_OUTPUT_FLAG_INTERACTIVE)
+            app_type = direct_app_type;
+        else
+            app_type = usecase->stream.out->app_type_cfg.app_type;
         app_type_cfg[len++] = app_type;
         app_type_cfg[len++] = acdb_dev_id;
         if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
@@ -2160,3 +2216,100 @@
 exit:
     return ret;
 }
+
+int audio_extn_utils_set_pan_scale_params(
+            struct stream_out *out,
+            struct mix_matrix_params *mm_params)
+{
+    int ret = -EINVAL, i = 0, j = 0;
+
+    if (mm_params == NULL && out != NULL) {
+        ALOGE("%s:: Invalid mix matrix params", __func__);
+        goto exit;
+    }
+
+    if (mm_params->num_output_channels > MAX_CHANNELS_SUPPORTED ||
+        mm_params->num_output_channels <= 0 ||
+        mm_params->num_input_channels > MAX_CHANNELS_SUPPORTED ||
+        mm_params->num_input_channels <= 0)
+        goto exit;
+
+    out->pan_scale_params.num_output_channels = mm_params->num_output_channels;
+    out->pan_scale_params.num_input_channels = mm_params->num_input_channels;
+    out->pan_scale_params.has_output_channel_map =
+                                        mm_params->has_output_channel_map;
+    for (i = 0; i < mm_params->num_output_channels; i++)
+        out->pan_scale_params.output_channel_map[i] =
+                                         mm_params->output_channel_map[i];
+
+    out->pan_scale_params.has_input_channel_map =
+                                         mm_params->has_input_channel_map;
+    for (i = 0; i < mm_params->num_input_channels; i++)
+        out->pan_scale_params.input_channel_map[i] =
+                                         mm_params->input_channel_map[i];
+
+    out->pan_scale_params.has_mixer_coeffs = mm_params->has_mixer_coeffs;
+    for (i = 0; i < mm_params->num_output_channels; i++)
+        for (j = 0; j < mm_params->num_input_channels; j++) {
+            //Convert the channel coefficient gains in Q14 format
+            out->pan_scale_params.mixer_coeffs[i][j] =
+                               mm_params->mixer_coeffs[i][j] * (2 << 13);
+        }
+
+    ret = platform_set_stream_pan_scale_params(out->dev->platform,
+                                               out->pcm_device_id,
+                                               out->pan_scale_params);
+
+exit:
+    return ret;
+}
+
+int audio_extn_utils_set_downmix_params(
+            struct stream_out *out,
+            struct mix_matrix_params *mm_params)
+{
+    int ret = -EINVAL, i = 0, j = 0;
+    struct audio_usecase *usecase = NULL;
+
+    if (mm_params == NULL && out != NULL) {
+        ALOGE("%s:: Invalid mix matrix params", __func__);
+        goto exit;
+    }
+
+    if (mm_params->num_output_channels > MAX_CHANNELS_SUPPORTED ||
+        mm_params->num_output_channels <= 0 ||
+        mm_params->num_input_channels > MAX_CHANNELS_SUPPORTED ||
+        mm_params->num_input_channels <= 0)
+        goto exit;
+
+    usecase = get_usecase_from_list(out->dev, out->usecase);
+    out->downmix_params.num_output_channels = mm_params->num_output_channels;
+    out->downmix_params.num_input_channels = mm_params->num_input_channels;
+
+    out->downmix_params.has_output_channel_map =
+                                        mm_params->has_output_channel_map;
+    for (i = 0; i < mm_params->num_output_channels; i++) {
+        out->downmix_params.output_channel_map[i] =
+                                          mm_params->output_channel_map[i];
+    }
+
+    out->downmix_params.has_input_channel_map =
+                                        mm_params->has_input_channel_map;
+    for (i = 0; i < mm_params->num_input_channels; i++)
+        out->downmix_params.input_channel_map[i] =
+                                          mm_params->input_channel_map[i];
+
+    out->downmix_params.has_mixer_coeffs = mm_params->has_mixer_coeffs;
+    for (i = 0; i < mm_params->num_output_channels; i++)
+        for (j = 0; j < mm_params->num_input_channels; j++)
+            out->downmix_params.mixer_coeffs[i][j] =
+                               mm_params->mixer_coeffs[i][j];
+
+    ret = platform_set_stream_downmix_params(out->dev->platform,
+                                             out->pcm_device_id,
+                                             usecase->out_snd_device,
+                                             out->downmix_params);
+
+exit:
+    return ret;
+}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 996a9a1..6029c4a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -64,6 +64,7 @@
 
 #include <hardware/audio_effect.h>
 #include <system/thread_defs.h>
+#include <tinyalsa/asoundlib.h>
 #include <audio_effects/effect_aec.h>
 #include <audio_effects/effect_ns.h>
 #include <audio_utils/format.h>
@@ -118,6 +119,11 @@
 static unsigned int configured_low_latency_capture_period_size =
         LOW_LATENCY_CAPTURE_PERIOD_SIZE;
 
+#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
+#define MMAP_PERIOD_COUNT_MIN 32
+#define MMAP_PERIOD_COUNT_MAX 512
+#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
+
 struct pcm_config pcm_config_deep_buffer = {
     .channels = 2,
     .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
@@ -165,6 +171,19 @@
     .avail_min = 0,
 };
 
+struct pcm_config pcm_config_mmap_playback = {
+    .channels = 2,
+    .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
+    .period_size = MMAP_PERIOD_SIZE,
+    .period_count = MMAP_PERIOD_COUNT_DEFAULT,
+    .format = PCM_FORMAT_S16_LE,
+    .start_threshold = MMAP_PERIOD_SIZE*8,
+    .stop_threshold = INT32_MAX,
+    .silence_threshold = 0,
+    .silence_size = 0,
+    .avail_min = MMAP_PERIOD_SIZE, //1 ms
+};
+
 struct pcm_config pcm_config_audio_capture = {
     .channels = 2,
     .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
@@ -184,6 +203,19 @@
     .avail_min = ULL_PERIOD_SIZE, //1 ms
 };
 
+struct pcm_config pcm_config_mmap_capture = {
+    .channels = 2,
+    .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
+    .period_size = MMAP_PERIOD_SIZE,
+    .period_count = MMAP_PERIOD_COUNT_DEFAULT,
+    .format = PCM_FORMAT_S16_LE,
+    .start_threshold = 0,
+    .stop_threshold = INT_MAX,
+    .silence_threshold = 0,
+    .silence_size = 0,
+    .avail_min = MMAP_PERIOD_SIZE, //1 ms
+};
+
 #define AFE_PROXY_CHANNEL_COUNT 2
 #define AFE_PROXY_SAMPLING_RATE 48000
 
@@ -242,6 +274,8 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
+    [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
+    [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
 
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
@@ -250,7 +284,8 @@
     [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
     [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
-    [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
+    [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
+
     [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
     [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
     [USECASE_VOICE_CALL] = "voice-call",
@@ -283,6 +318,15 @@
 
     [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
     [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
+    /* For Interactive Audio Streams */
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
 };
 
 static const audio_usecase_t offload_usecases[] = {
@@ -297,6 +341,17 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
 };
 
+static const audio_usecase_t interactive_usecases[] = {
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
+};
+
 #define STRING_TO_ENUM(string) { #string, string }
 
 struct string_to_enum {
@@ -1460,6 +1515,84 @@
     return active;
 }
 
+uint32_t adev_get_dsp_bit_width_enforce_mode()
+{
+    if (adev == NULL) {
+        ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
+        return 0;
+    }
+    return adev->dsp_bit_width_enforce_mode;
+}
+
+static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
+{
+    char value[PROPERTY_VALUE_MAX];
+    int trial;
+    uint32_t dsp_bit_width_enforce_mode = 0;
+
+    if (!mixer) {
+        ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
+                __func__);
+        return 0;
+    }
+
+    if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
+                        value, NULL) > 0) {
+        trial = atoi(value);
+        switch (trial) {
+        case 16:
+            dsp_bit_width_enforce_mode = 16;
+            break;
+        case 24:
+            dsp_bit_width_enforce_mode = 24;
+            break;
+        case 32:
+            dsp_bit_width_enforce_mode = 32;
+            break;
+       default:
+            dsp_bit_width_enforce_mode = 0;
+            ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
+            break;
+        }
+    }
+
+    return dsp_bit_width_enforce_mode;
+}
+
+static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
+                                                uint32_t enforce_mode,
+                                                bool enable)
+{
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "ASM Bit Width";
+    uint32_t asm_bit_width_mode = 0;
+
+    if (enforce_mode == 0) {
+        ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
+        return;
+    }
+
+    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+                __func__, mixer_ctl_name);
+        return;
+    }
+
+    if (enable)
+        asm_bit_width_mode = enforce_mode;
+    else
+        asm_bit_width_mode = 0;
+
+    ALOGV("%s DSP bit width feature status is %d width=%d",
+        __func__, enable, asm_bit_width_mode);
+    if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
+        ALOGE("%s: Could not set ASM biwidth %d", __func__,
+                asm_bit_width_mode);
+
+    return;
+}
+
 /*
  * if native DSD playback active
  */
@@ -1731,10 +1864,10 @@
             voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
     }
 
-    if ((usecase->out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
+    if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
         (!audio_extn_a2dp_is_ready())) {
         ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
-        usecase->out_snd_device = SND_DEVICE_OUT_SPEAKER;
+        out_snd_device = SND_DEVICE_OUT_SPEAKER;
     }
 
     /* Disable current sound devices */
@@ -1976,60 +2109,75 @@
                                  adev->perf_lock_opts_size);
     select_devices(adev, in->usecase);
 
-    ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
-          __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
-
-   if (audio_extn_cin_attached_usecase(in->usecase)) {
+    if (audio_extn_cin_attached_usecase(in->usecase)) {
        ret = audio_extn_cin_start_input_stream(in);
        if (ret)
            goto error_open;
        else
            goto done_open;
-   }
-
-    unsigned int flags = PCM_IN;
-    unsigned int pcm_open_retry_count = 0;
-
-    if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
-        flags |= PCM_MMAP | PCM_NOIRQ;
-        pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
-    } else if (in->realtime) {
-        flags |= PCM_MMAP | PCM_NOIRQ;
     }
 
-    while (1) {
-        in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
-                           flags, &in->config);
+    if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
         if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
-            ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
-            if (in->pcm != NULL) {
+            ALOGE("%s: pcm stream not ready", __func__);
+            goto error_open;
+        }
+        ret = pcm_start(in->pcm);
+        if (ret < 0) {
+            ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
+            goto error_open;
+        }
+    } else {
+        unsigned int flags = PCM_IN | PCM_MONOTONIC;
+        unsigned int pcm_open_retry_count = 0;
+
+        if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
+            flags |= PCM_MMAP | PCM_NOIRQ;
+            pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
+        } else if (in->realtime) {
+            flags |= PCM_MMAP | PCM_NOIRQ;
+        }
+
+        ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
+              __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
+
+        while (1) {
+            in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
+                               flags, &in->config);
+            if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
+                ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
+                if (in->pcm != NULL) {
+                    pcm_close(in->pcm);
+                    in->pcm = NULL;
+                }
+                if (pcm_open_retry_count-- == 0) {
+                    ret = -EIO;
+                    goto error_open;
+                }
+                usleep(PROXY_OPEN_WAIT_TIME * 1000);
+                continue;
+            }
+            break;
+        }
+
+        ALOGV("%s: pcm_prepare", __func__);
+        ret = pcm_prepare(in->pcm);
+        if (ret < 0) {
+            ALOGE("%s: pcm_prepare returned %d", __func__, ret);
+            pcm_close(in->pcm);
+            in->pcm = NULL;
+            goto error_open;
+        }
+        register_in_stream(in);
+        if (in->realtime) {
+            ret = pcm_start(in->pcm);
+            if (ret < 0) {
+                ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
                 pcm_close(in->pcm);
                 in->pcm = NULL;
-            }
-            if (pcm_open_retry_count-- == 0) {
-                ret = -EIO;
                 goto error_open;
             }
-            usleep(PROXY_OPEN_WAIT_TIME * 1000);
-            continue;
         }
-        break;
-    }
-
-    ALOGV("%s: pcm_prepare", __func__);
-    ret = pcm_prepare(in->pcm);
-    if (ret < 0) {
-        ALOGE("%s: pcm_prepare returned %d", __func__, ret);
-        pcm_close(in->pcm);
-        in->pcm = NULL;
-        goto error_open;
-    }
-
-    register_in_stream(in);
-    if (in->realtime) {
-        ret = pcm_start(in->pcm);
-        if (ret < 0)
-            goto error_open;
     }
 
 done_open:
@@ -2099,6 +2247,50 @@
     }
 }
 
+bool is_interactive_usecase(audio_usecase_t uc_id)
+{
+    unsigned int i;
+    for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
+        if (uc_id == interactive_usecases[i])
+            return true;
+    }
+    return false;
+}
+
+static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
+{
+    audio_usecase_t ret_uc = USECASE_INVALID;
+    unsigned int intract_uc_index;
+    unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
+
+    ALOGV("%s: num_usecase: %d", __func__, num_usecase);
+    for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
+        if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
+            adev->interactive_usecase_state |= 0x1 << intract_uc_index;
+            ret_uc = interactive_usecases[intract_uc_index];
+            break;
+        }
+    }
+
+    ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
+    return ret_uc;
+}
+
+static void free_interactive_usecase(struct audio_device *adev,
+                                 audio_usecase_t uc_id)
+{
+    unsigned int interact_uc_index;
+    unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
+
+    for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
+        if (interactive_usecases[interact_uc_index] == uc_id) {
+            adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
+            break;
+        }
+    }
+    ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
+}
+
 bool is_offload_usecase(audio_usecase_t uc_id)
 {
     unsigned int i;
@@ -2330,6 +2522,12 @@
     /* 2. Disable the rx device */
     disable_snd_device(adev, uc_info->out_snd_device);
 
+    if (is_offload_usecase(out->usecase)) {
+        audio_enable_asm_bit_width_enforce_mode(adev->mixer,
+                                                adev->dsp_bit_width_enforce_mode,
+                                                false);
+    }
+
     list_remove(&uc_info->list);
     free(uc_info);
     out->started = 0;
@@ -2346,7 +2544,7 @@
     if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
         audio_extn_keep_alive_start();
 
-    if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
         if (ret < 0)
             ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
@@ -2460,7 +2658,18 @@
 
     ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
           __func__, adev->snd_card, out->pcm_device_id, out->config.format);
-    if (!is_offload_usecase(out->usecase)) {
+
+    if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
+        if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
+            ALOGE("%s: pcm stream not ready", __func__);
+            goto error_open;
+        }
+        ret = pcm_start(out->pcm);
+        if (ret < 0) {
+            ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
+            goto error_open;
+        }
+    } else if (!is_offload_usecase(out->usecase)) {
         unsigned int flags = PCM_OUT;
         unsigned int pcm_open_retry_count = 0;
         if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
@@ -2528,6 +2737,9 @@
     } else {
         platform_set_stream_channel_map(adev->platform, out->channel_mask,
                    out->pcm_device_id, &out->channel_map_param.channel_map[0]);
+        audio_enable_asm_bit_width_enforce_mode(adev->mixer,
+                                                adev->dsp_bit_width_enforce_mode,
+                                                true);
         out->pcm = NULL;
         out->compr = compress_open(adev->snd_card,
                                    out->pcm_device_id,
@@ -2587,7 +2799,7 @@
     audio_extn_perf_lock_release(&adev->perf_lock_handle);
     ALOGD("%s: exit", __func__);
 
-    if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
         if (ret < 0)
             ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
@@ -2753,7 +2965,9 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
 
-    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
+    if (is_interactive_usecase(out->usecase)) {
+        return out->config.period_size;
+    } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
         if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
             return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
         else
@@ -2796,6 +3010,7 @@
     struct audio_device *adev = out->dev;
     struct audio_usecase *uc_info;
     struct listnode *node;
+    bool do_stop = true;
 
     ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
           stream, out->usecase, use_case_table[out->usecase]);
@@ -2822,6 +3037,10 @@
                 pcm_close(out->pcm);
                 out->pcm = NULL;
             }
+            if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
+                do_stop = out->playback_started;
+                out->playback_started = false;
+            }
         } else {
             ALOGD("copl(%p):standby", out);
             out->send_next_track_params = false;
@@ -2833,7 +3052,9 @@
                 out->compr = NULL;
             }
         }
-        stop_output_stream(out);
+        if (do_stop) {
+            stop_output_stream(out);
+        }
         //restore output device for active usecase when current snd device and output device mismatch
         list_for_each(node, &adev->usecase_list) {
             uc_info = node_to_item(node, struct audio_usecase, list);
@@ -3113,7 +3334,7 @@
                     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))) {
+                    (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
                     pthread_mutex_lock(&out->compr_mute_lock);
                     out->a2dp_compress_mute = false;
                     out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
@@ -3334,7 +3555,8 @@
         lock_output_stream(out);
         latency = audio_extn_utils_compress_get_dsp_latency(out);
         pthread_mutex_unlock(&out->lock);
-    } else if (out->realtime) {
+    } else if ((out->realtime) ||
+            (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
         // since the buffer won't be filled up faster than realtime,
         // return a smaller number
         if (out->config.rate)
@@ -3462,6 +3684,20 @@
     return -ENOSYS;
 }
 
+static void update_frames_written(struct stream_out *out, size_t bytes)
+{
+    size_t bpf = 0;
+
+    if (is_offload_usecase(out->usecase) && !out->non_blocking &&
+        !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
+        bpf = 1;
+    else if (!is_offload_usecase(out->usecase))
+        bpf = audio_bytes_per_sample(out->format) *
+             audio_channel_count_from_out_mask(out->channel_mask);
+    if (bpf != 0)
+        out->written += bytes / bpf;
+}
+
 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
                          size_t bytes)
 {
@@ -3479,14 +3715,6 @@
             pthread_mutex_unlock(&out->lock);
             return -ENETRESET;
         } else {
-            /* increase written size during SSR to avoid mismatch
-             * with the written frames count in AF
-             */
-            // bytes per frame
-            size_t bpf = audio_bytes_per_sample(out->format) *
-                         audio_channel_count_from_out_mask(out->channel_mask);
-            if (bpf != 0)
-                out->written += bytes / bpf;
             ALOGD(" %s: sound card is not active/SSR state", __func__);
             ret= -EIO;
             goto exit;
@@ -3495,12 +3723,15 @@
 
     if (audio_extn_passthru_should_drop_data(out)) {
         ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
-        if ((audio_bytes_per_sample(out->format) != 0) && (out->config.channels != 0))
-            out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
         ret = -EIO;
         goto exit;
     }
 
+    if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
     if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
         /*ADD audio_extn_passthru_is_passthrough_stream(out) check*/
         if ((audio_extn_passthru_is_enabled()) &&
@@ -3515,10 +3746,6 @@
         (audio_extn_a2dp_is_suspended())) {
         if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
             if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
-                size_t bpf = audio_bytes_per_sample(out->format) *
-                    audio_channel_count_from_out_mask(out->channel_mask);
-                if (bpf != 0)
-                    out->written += bytes / bpf;
                 ret = -EIO;
                 goto exit;
             }
@@ -3596,6 +3823,9 @@
         } else
             ret = compress_write(out->compr, buffer, bytes);
 
+        if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
+            update_frames_written(out, bytes);
+
         if (ret < 0)
             ret = -errno;
         ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
@@ -3610,8 +3840,6 @@
             out_on_error(&out->stream.common);
             return ret;
         }
-        if ( ret == (ssize_t)bytes && !out->non_blocking)
-            out->written += bytes;
 
         /* Call compr start only when non-zero bytes of data is there to be rendered */
         if (!out->playback_started && ret > 0) {
@@ -3690,14 +3918,13 @@
 
             if (ret < 0)
                 ret = -errno;
-            else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
-                out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
-            else
+            else if (ret > 0)
                 ret = -EINVAL;
         }
     }
 
 exit:
+    update_frames_written(out, bytes);
     if (-ENETRESET == ret) {
         out->card_status = CARD_STATUS_OFFLINE;
     }
@@ -3987,6 +4214,177 @@
     return -ENOSYS;
 }
 
+static int out_stop(const struct audio_stream_out* stream)
+{
+    struct stream_out *out = (struct stream_out *)stream;
+    struct audio_device *adev = out->dev;
+    int ret = -ENOSYS;
+
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&adev->lock);
+    if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
+            out->playback_started && out->pcm != NULL) {
+        pcm_stop(out->pcm);
+        ret = stop_output_stream(out);
+        out->playback_started = false;
+    }
+    pthread_mutex_unlock(&adev->lock);
+    return ret;
+}
+
+static int out_start(const struct audio_stream_out* stream)
+{
+    struct stream_out *out = (struct stream_out *)stream;
+    struct audio_device *adev = out->dev;
+    int ret = -ENOSYS;
+
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&adev->lock);
+    if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
+            !out->playback_started && out->pcm != NULL) {
+        ret = start_output_stream(out);
+        if (ret == 0) {
+            out->playback_started = true;
+        }
+    }
+    pthread_mutex_unlock(&adev->lock);
+    return ret;
+}
+
+/*
+ * Modify config->period_count based on min_size_frames
+ */
+static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
+{
+    int periodCountRequested = (min_size_frames + config->period_size - 1)
+                               / config->period_size;
+    int periodCount = MMAP_PERIOD_COUNT_MIN;
+
+    ALOGV("%s original config.period_size = %d config.period_count = %d",
+          __func__, config->period_size, config->period_count);
+
+    while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
+        periodCount *= 2;
+    }
+    config->period_count = periodCount;
+
+    ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
+}
+
+static int out_create_mmap_buffer(const struct audio_stream_out *stream,
+                                  int32_t min_size_frames,
+                                  struct audio_mmap_buffer_info *info)
+{
+    struct stream_out *out = (struct stream_out *)stream;
+    struct audio_device *adev = out->dev;
+    int ret = 0;
+    unsigned int offset1;
+    unsigned int frames1;
+    const char *step = "";
+    uint32_t mmap_size;
+
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&adev->lock);
+
+    if (info == NULL || min_size_frames == 0) {
+        ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
+        ret = -EINVAL;
+        goto exit;
+    }
+    if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
+        ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
+        ret = -ENOSYS;
+        goto exit;
+    }
+    out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+    if (out->pcm_device_id < 0) {
+        ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
+              __func__, out->pcm_device_id, out->usecase);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    adjust_mmap_period_count(&out->config, min_size_frames);
+
+    ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
+          __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
+    out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
+                        (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
+    if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
+        step = "open";
+        ret = -ENODEV;
+        goto exit;
+    }
+    ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
+    if (ret < 0)  {
+        step = "begin";
+        goto exit;
+    }
+    info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
+    info->burst_size_frames = out->config.period_size;
+    ret = platform_get_mmap_data_fd(adev->platform,
+                                    out->pcm_device_id, 0 /*playback*/,
+                                    &info->shared_memory_fd,
+                                    &mmap_size);
+    if (ret < 0) {
+        step = "get_mmap_fd";
+        goto exit;
+    }
+    memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
+                                                               info->buffer_size_frames));
+
+    ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
+    if (ret < 0) {
+        step = "commit";
+        goto exit;
+    }
+
+    out->standby = false;
+    ret = 0;
+
+    ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
+          __func__, info->shared_memory_address, info->buffer_size_frames);
+
+exit:
+    if (ret != 0) {
+        if (out->pcm == NULL) {
+            ALOGE("%s: %s - %d", __func__, step, ret);
+        } else {
+            ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
+            pcm_close(out->pcm);
+            out->pcm = NULL;
+        }
+    }
+    pthread_mutex_unlock(&adev->lock);
+    return ret;
+}
+
+static int out_get_mmap_position(const struct audio_stream_out *stream,
+                                  struct audio_mmap_position *position)
+{
+    struct stream_out *out = (struct stream_out *)stream;
+    ALOGVV("%s", __func__);
+    if (position == NULL) {
+        return -EINVAL;
+    }
+    if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
+        return -ENOSYS;
+    }
+    if (out->pcm == NULL) {
+        return -ENOSYS;
+    }
+
+    struct timespec ts = { 0, 0 };
+    int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
+    if (ret < 0) {
+        ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
+        return ret;
+    }
+    position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
+    return 0;
+}
+
+
 /** audio_stream_in implementation **/
 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
 {
@@ -4045,6 +4443,7 @@
     int status = 0;
     ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
           stream, in->usecase, use_case_table[in->usecase]);
+    bool do_stop = true;
 
     lock_input_stream(in);
     if (!in->standby && in->is_st_session) {
@@ -4062,6 +4461,9 @@
         if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
             voice_extn_compress_voip_close_input_stream(stream);
             ALOGD("VOIP input entered standby");
+        } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
+            do_stop = in->capture_started;
+            in->capture_started = false;
         } else {
             if (audio_extn_cin_attached_usecase(in->usecase))
                 audio_extn_cin_stop_input_stream(in);
@@ -4071,6 +4473,14 @@
             }
             status = stop_input_stream(in);
         }
+        if (in->pcm) {
+            pcm_close(in->pcm);
+            in->pcm = NULL;
+        }
+
+        if (do_stop) {
+            status = stop_input_stream(in);
+        }
         pthread_mutex_unlock(&adev->lock);
     }
     pthread_mutex_unlock(&in->lock);
@@ -4249,6 +4659,11 @@
         return bytes;
     }
 
+    if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
+        ret = -ENOSYS;
+        goto exit;
+    }
+
     if (in->standby) {
         pthread_mutex_lock(&adev->lock);
         if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
@@ -4384,13 +4799,159 @@
     return add_remove_audio_effect(stream, effect, false);
 }
 
+static int in_stop(const struct audio_stream_in* stream)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+    struct audio_device *adev = in->dev;
+
+    int ret = -ENOSYS;
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&adev->lock);
+    if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
+            in->capture_started && in->pcm != NULL) {
+        pcm_stop(in->pcm);
+        ret = stop_input_stream(in);
+        in->capture_started = false;
+    }
+    pthread_mutex_unlock(&adev->lock);
+    return ret;
+}
+
+static int in_start(const struct audio_stream_in* stream)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+    struct audio_device *adev = in->dev;
+    int ret = -ENOSYS;
+
+    ALOGV("%s in %p", __func__, in);
+    pthread_mutex_lock(&adev->lock);
+    if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
+            !in->capture_started && in->pcm != NULL) {
+        if (!in->capture_started) {
+            ret = start_input_stream(in);
+            if (ret == 0) {
+                in->capture_started = true;
+            }
+        }
+    }
+    pthread_mutex_unlock(&adev->lock);
+    return ret;
+}
+
+static int in_create_mmap_buffer(const struct audio_stream_in *stream,
+                                  int32_t min_size_frames,
+                                  struct audio_mmap_buffer_info *info)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+    struct audio_device *adev = in->dev;
+    int ret = 0;
+    unsigned int offset1;
+    unsigned int frames1;
+    const char *step = "";
+
+    pthread_mutex_lock(&adev->lock);
+    ALOGV("%s in %p", __func__, in);
+
+    if (info == NULL || min_size_frames == 0) {
+        ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
+        ret = -EINVAL;
+        goto exit;
+    }
+    if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
+        ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
+        ALOGV("%s in %p", __func__, in);
+        ret = -ENOSYS;
+        goto exit;
+    }
+    in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
+    if (in->pcm_device_id < 0) {
+        ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
+              __func__, in->pcm_device_id, in->usecase);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    adjust_mmap_period_count(&in->config, min_size_frames);
+
+    ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
+          __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
+    in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
+                        (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
+    if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
+        step = "open";
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
+    if (ret < 0)  {
+        step = "begin";
+        goto exit;
+    }
+    info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
+    info->burst_size_frames = in->config.period_size;
+    info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
+
+    memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
+                                                                info->buffer_size_frames));
+
+    ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
+    if (ret < 0) {
+        step = "commit";
+        goto exit;
+    }
+
+    in->standby = false;
+    ret = 0;
+
+    ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
+          __func__, info->shared_memory_address, info->buffer_size_frames);
+
+exit:
+    if (ret != 0) {
+        if (in->pcm == NULL) {
+            ALOGE("%s: %s - %d", __func__, step, ret);
+        } else {
+            ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
+            pcm_close(in->pcm);
+            in->pcm = NULL;
+        }
+    }
+    pthread_mutex_unlock(&adev->lock);
+    return ret;
+}
+
+static int in_get_mmap_position(const struct audio_stream_in *stream,
+                                  struct audio_mmap_position *position)
+{
+    struct stream_in *in = (struct stream_in *)stream;
+    ALOGVV("%s", __func__);
+    if (position == NULL) {
+        return -EINVAL;
+    }
+    if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
+        return -ENOSYS;
+    }
+    if (in->pcm == NULL) {
+        return -ENOSYS;
+    }
+    struct timespec ts = { 0, 0 };
+    int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
+    if (ret < 0) {
+        ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
+        return ret;
+    }
+    position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
+    return 0;
+}
+
 int adev_open_output_stream(struct audio_hw_device *dev,
-                                   audio_io_handle_t handle,
-                                   audio_devices_t devices,
-                                   audio_output_flags_t flags,
-                                   struct audio_config *config,
-                                   struct audio_stream_out **stream_out,
-                                   const char *address __unused)
+                            audio_io_handle_t handle,
+                            audio_devices_t devices,
+                            audio_output_flags_t flags,
+                            struct audio_config *config,
+                            struct audio_stream_out **stream_out,
+                            const char *address __unused)
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
@@ -4772,11 +5333,21 @@
 
         channels = audio_channel_count_from_out_mask(out->channel_mask);
 
-        if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
+        if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
+            out->usecase = get_interactive_usecase(adev);
+            out->config = pcm_config_low_latency;
+        } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
             out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
             out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
                                                out->flags);
             out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
+        } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
+            out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
+            out->config = pcm_config_mmap_playback;
+            out->stream.start = out_start;
+            out->stream.stop = out_stop;
+            out->stream.create_mmap_buffer = out_create_mmap_buffer;
+            out->stream.get_mmap_position = out_get_mmap_position;
         } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
             out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
             out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
@@ -4883,7 +5454,11 @@
     out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
     out->stream.get_presentation_position = out_get_presentation_position;
 
-    out->af_period_multiplier  = out->realtime ? af_period_multiplier : 1;
+    if (out->realtime)
+        out->af_period_multiplier = af_period_multiplier;
+    else
+        out->af_period_multiplier = 1;
+
     out->standby = 1;
     /* out->muted = false; by calloc() */
     /* out->written = 0; by calloc() */
@@ -4914,7 +5489,7 @@
     /* setup a channel for client <--> adsp communication for stream events */
     if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
             (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
-            (audio_extn_ip_hdlr_intf_supported(config->format))) {
+            (audio_extn_ip_hdlr_intf_supported(config->format, audio_extn_passthru_is_direct_passthrough(out)))) {
         hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
                 out->usecase, PCM_PLAYBACK);
         hdlr_stream_cfg.flags = out->flags;
@@ -4926,7 +5501,7 @@
             out->adsp_hdlr_stream_handle = NULL;
         }
     }
-    if (audio_extn_ip_hdlr_intf_supported(config->format)) {
+    if (audio_extn_ip_hdlr_intf_supported(config->format, audio_extn_passthru_is_direct_passthrough(out))) {
         ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
@@ -4966,7 +5541,7 @@
         out->adsp_hdlr_stream_handle = NULL;
     }
 
-    if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
         audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
         out->ip_hdlr_handle = NULL;
     }
@@ -4992,6 +5567,9 @@
 
     out->a2dp_compress_mute = false;
 
+    if (is_interactive_usecase(out->usecase))
+        free_interactive_usecase(adev, out->usecase);
+
     if (out->convert_buffer != NULL) {
         free(out->convert_buffer);
         out->convert_buffer = NULL;
@@ -5409,16 +5987,26 @@
 
     in->usecase = USECASE_AUDIO_RECORD;
     if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
-            (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
+        (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 (in->realtime) {
+    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;
@@ -5542,7 +6130,8 @@
             in->config.rate = in->sample_rate;
 #else
         if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
-               (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
+               (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
+                voice_extn_compress_voip_is_active(in->dev)) &&
                (voice_extn_compress_voip_is_format_supported(in->format)) &&
                (in->config.rate == 8000 || in->config.rate == 16000 ||
                 in->config.rate == 32000 || in->config.rate == 48000) &&
@@ -5908,6 +6497,7 @@
     adev->perf_lock_opts[0] = 0x101;
     adev->perf_lock_opts[1] = 0x20E;
     adev->perf_lock_opts_size = 2;
+    adev->dsp_bit_width_enforce_mode = 0;
 
     /* Loads platform specific libraries dynamically */
     adev->platform = platform_init(adev);
@@ -6020,6 +6610,8 @@
 
     audio_extn_ds2_enable(adev);
     *device = &adev->device.common;
+    adev->dsp_bit_width_enforce_mode =
+        adev_init_dsp_bit_width_enforce_mode(adev->mixer);
 
     audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
                                              &adev->streams_output_cfg_list,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 71de46a..0a6d85b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -118,6 +118,7 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD8,
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
     USECASE_AUDIO_PLAYBACK_ULL,
+    USECASE_AUDIO_PLAYBACK_MMAP,
 
     /* FM usecase */
     USECASE_AUDIO_PLAYBACK_FM,
@@ -139,6 +140,7 @@
     USECASE_AUDIO_RECORD_VOIP,
     /* Voice usecase */
     USECASE_VOICE_CALL,
+    USECASE_AUDIO_RECORD_MMAP,
 
     /* Voice extension usecases */
     USECASE_VOICE2_CALL,
@@ -168,6 +170,15 @@
     USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
 
     USECASE_AUDIO_TRANSCODE_LOOPBACK,
+
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
+    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
     AUDIO_USECASE_MAX
 };
 
@@ -310,6 +321,8 @@
 
     char pm_qos_mixer_path[MAX_MIXER_PATH_LEN];
     int dynamic_pm_qos_enabled;
+    mix_matrix_params_t pan_scale_params;
+    mix_matrix_params_t downmix_params;
 };
 
 struct stream_in {
@@ -342,6 +355,7 @@
 
     struct audio_device *dev;
     card_status_t card_status;
+    int capture_started;
 };
 
 typedef enum {
@@ -479,8 +493,10 @@
     bool asrc_mode_enabled;
     qahwi_device_t qahwi_dev;
     bool vr_audio_mode_enabled;
+    uint32_t dsp_bit_width_enforce_mode;
     bool bt_sco_on;
     struct audio_device_config_param *device_cfg_params;
+    unsigned int interactive_usecase_state;
 };
 
 int select_devices(struct audio_device *adev,
@@ -506,6 +522,8 @@
 
 bool audio_is_dsd_native_stream_active(struct audio_device *adev);
 
+uint32_t adev_get_dsp_bit_width_enforce_mode();
+
 int pcm_ioctl(struct pcm *pcm, int request, ...);
 
 audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
@@ -523,6 +541,8 @@
 void adev_close_output_stream(struct audio_hw_device *dev __unused,
                               struct audio_stream_out *stream);
 
+bool is_interactive_usecase(audio_usecase_t uc_id);
+
 #define LITERAL_TO_STRING(x) #x
 #define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\
             __FILE__ ":" LITERAL_TO_STRING(__LINE__)\
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index cfb5486..52e3138 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -40,6 +40,10 @@
 #include <dirent.h>
 #include <linux/msm_audio.h>
 
+#if defined(PLATFORM_MSMFALCON)
+#include <sound/devdep_params.h>
+#endif
+
 #ifdef DYNAMIC_LOG_ENABLED
 #include <log_xml_parser.h>
 #define LOG_MASK HAL_MOD_FILE_PLATFORM
@@ -336,6 +340,10 @@
     [USECASE_AUDIO_HFP_SCO_WB] = {HFP_PCM_RX, HFP_SCO_RX},
     [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
     [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_MMAP] = {MMAP_PLAYBACK_PCM_DEVICE,
+                                     MMAP_PLAYBACK_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_MMAP] = {MMAP_RECORD_PCM_DEVICE,
+                                   MMAP_RECORD_PCM_DEVICE},
     [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
     [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
     [USECASE_VOWLAN_CALL] = {VOWLAN_CALL_PCM_DEVICE, VOWLAN_CALL_PCM_DEVICE},
@@ -369,6 +377,23 @@
     [USECASE_AUDIO_PLAYBACK_VOIP] = {AUDIO_PLAYBACK_VOIP_PCM_DEVICE, AUDIO_PLAYBACK_VOIP_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_VOIP] = {AUDIO_RECORD_VOIP_PCM_DEVICE, AUDIO_RECORD_VOIP_PCM_DEVICE},
 
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE1, PLAYBACK_INTERACTIVE_STRM_DEVICE1},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE2, PLAYBACK_INTERACTIVE_STRM_DEVICE2},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE3, PLAYBACK_INTERACTIVE_STRM_DEVICE3},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE4, PLAYBACK_INTERACTIVE_STRM_DEVICE4},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE5, PLAYBACK_INTERACTIVE_STRM_DEVICE5},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE6, PLAYBACK_INTERACTIVE_STRM_DEVICE6},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE7, PLAYBACK_INTERACTIVE_STRM_DEVICE7},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE8, PLAYBACK_INTERACTIVE_STRM_DEVICE8},
+
 };
 
 /* Array to store sound devices */
@@ -812,6 +837,7 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD7)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MMAP)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS)},
@@ -819,6 +845,7 @@
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS3)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS4)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_MMAP)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
     {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
     {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
@@ -902,6 +929,7 @@
 #define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 #define ULL_PLATFORM_DELAY (6*1000LL)
+#define MMAP_PLATFORM_DELAY (3*1000LL)
 
 static void update_interface(const char *snd_card_name) {
      if (!strncmp(snd_card_name, "apq8009-tashalite-snd-card",
@@ -5024,6 +5052,8 @@
             return PCM_OFFLOAD_PLATFORM_DELAY;
         case USECASE_AUDIO_PLAYBACK_ULL:
             return ULL_PLATFORM_DELAY;
+        case USECASE_AUDIO_PLAYBACK_MMAP:
+            return MMAP_PLATFORM_DELAY;
         default:
             return 0;
     }
@@ -5858,6 +5888,10 @@
         backend_cfg.format = usecase->stream.out->format;
         backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
     }
+    /* enforce AFE bitwidth mode via backend_cfg */
+    if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
+                (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
+        backend_cfg.bit_width = adev->dsp_bit_width_enforce_mode;
 
     /*this is populated by check_codec_backend_cfg hence set default value to false*/
     backend_cfg.passthrough_enabled = false;
@@ -6161,6 +6195,147 @@
      *length = msm_be_id_array_len;
 }
 
+int platform_set_stream_pan_scale_params(void *platform,
+                                         int snd_id,
+                                         struct mix_matrix_params mm_params)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    struct mixer_ctl *ctl = NULL;
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    int ret = 0;
+    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;
+    }
+
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                          "Audio Stream %d Pan Scale Control", snd_id);
+    ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);
+
+    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);
+        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[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    pan_scale_data[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    pan_scale_data[length++] = 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];
+
+    ret = mixer_ctl_set_array(ctl, pan_scale_data, length);
+end:
+    return ret;
+}
+
+int platform_set_stream_downmix_params(void *platform,
+                                       int snd_id,
+                                       snd_device_t snd_device,
+                                       struct mix_matrix_params mm_params)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    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};
+    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);
+
+    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);
+        ret = -EINVAL;
+        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;
+
+    downmix_param_data[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    downmix_param_data[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    downmix_param_data[length++] = 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];
+
+    ret = mixer_ctl_set_array(ctl, downmix_param_data, length);
+end:
+    return ret;
+}
+
 int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask,
                                                int snd_id, uint8_t *input_channel_map)
 {
@@ -7220,3 +7395,40 @@
 
     return MAX_CODEC_BACKENDS;
 }
+
+#if defined(PLATFORM_MSMFALCON)
+int platform_get_mmap_data_fd(void *platform, int fe_dev, int dir, int *fd,
+                              uint32_t *size)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    int hw_fd = -1;
+    char dev_name[128];
+    struct snd_pcm_mmap_fd mmap_fd;
+    memset(&mmap_fd, 0, sizeof(mmap_fd));
+    mmap_fd.dir = dir;
+    snprintf(dev_name, sizeof(dev_name), "/dev/snd/hwC%uD%u",
+             adev->snd_card, HWDEP_FE_BASE+fe_dev);
+    hw_fd = open(dev_name, O_RDONLY);
+    if (hw_fd < 0) {
+        ALOGE("fe hw dep node open %d/%d failed", adev->snd_card, fe_dev);
+        return -1;
+    }
+    if (ioctl(hw_fd, SNDRV_PCM_IOCTL_MMAP_DATA_FD, &mmap_fd) < 0) {
+        ALOGE("fe hw dep node ioctl failed");
+        close(hw_fd);
+        return -1;
+    }
+    *fd = mmap_fd.fd;
+    *size = mmap_fd.size;
+    close(hw_fd); // mmap_fd should still be valid
+    return 0;
+}
+#else
+int platform_get_mmap_data_fd(void *platform __unused, int fe_dev __unused,
+                              int dir __unused, int *fd __unused,
+                              uint32_t *size __unused)
+{
+    return -1;
+}
+#endif
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 6aa4dc1..30ae2c7 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -350,6 +350,8 @@
 #define VOLTE_CALL_PCM_DEVICE 15
 #define QCHAT_CALL_PCM_DEVICE 37
 #define VOWLAN_CALL_PCM_DEVICE 16
+#define MMAP_PLAYBACK_PCM_DEVICE 2 // XXX: This must be overwritten
+#define MMAP_RECORD_PCM_DEVICE 2 // XXX: This must be overwritten
 
 #define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
 #define AFE_PROXY_RECORD_PCM_DEVICE 8
@@ -357,6 +359,15 @@
 #define TRANSCODE_LOOPBACK_RX_DEV_ID 43
 #define TRANSCODE_LOOPBACK_TX_DEV_ID 44
 
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE1 0
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE2 1
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE3 27
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE4 45
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE5 46
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE6 47
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE7 48
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE8 49
+
 #define PLATFORM_MAX_MIC_COUNT "input_mic_max_count"
 #define PLATFORM_DEFAULT_MIC_COUNT 2
 
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index f2201db..43aeaed 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1368,3 +1368,9 @@
 {
     return 0;
 }
+
+int platform_get_mmap_data_fd(void *platform, int fe_dev, int dir, int *fd,
+                              uint32_t *size)
+{
+    return -ENOSYS;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 98b275b..e88673b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -75,6 +75,9 @@
 #endif
 
 #include <linux/msm_audio.h>
+#if defined (PLATFORM_MSM8998) || (PLATFORM_SDM845)
+#include <sound/devdep_params.h>
+#endif
 
 #define LIB_ACDB_LOADER "libacdbloader.so"
 #define CVD_VERSION_MIXER_CTL "CVD Version"
@@ -311,6 +314,10 @@
     [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
     [USECASE_AUDIO_HFP_SCO_WB] = {HFP_PCM_RX, HFP_SCO_RX},
     [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_MMAP] = {MMAP_PLAYBACK_PCM_DEVICE,
+            MMAP_PLAYBACK_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_MMAP] = {MMAP_RECORD_PCM_DEVICE,
+            MMAP_RECORD_PCM_DEVICE},
     [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
     [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
     [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
@@ -348,6 +355,22 @@
 
     [USECASE_AUDIO_PLAYBACK_VOIP] = {AUDIO_PLAYBACK_VOIP_PCM_DEVICE, AUDIO_PLAYBACK_VOIP_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_VOIP] = {AUDIO_RECORD_VOIP_PCM_DEVICE, AUDIO_RECORD_VOIP_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE1, PLAYBACK_INTERACTIVE_STRM_DEVICE1},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE2, PLAYBACK_INTERACTIVE_STRM_DEVICE2},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE3, PLAYBACK_INTERACTIVE_STRM_DEVICE3},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE4, PLAYBACK_INTERACTIVE_STRM_DEVICE4},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE5, PLAYBACK_INTERACTIVE_STRM_DEVICE5},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE6, PLAYBACK_INTERACTIVE_STRM_DEVICE6},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE7, PLAYBACK_INTERACTIVE_STRM_DEVICE7},
+    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] =
+                     {PLAYBACK_INTERACTIVE_STRM_DEVICE8, PLAYBACK_INTERACTIVE_STRM_DEVICE8},
 
 };
 
@@ -790,12 +813,14 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD7)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MMAP)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS2)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS3)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS4)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_MMAP)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
     {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
     {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
@@ -929,11 +954,11 @@
 static int msm_be_id_array_len  =
     sizeof(msm_device_to_be_id) / sizeof(msm_device_to_be_id[0]);
 
-
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
 #define ULL_PLATFORM_DELAY         (6*1000LL)
+#define MMAP_PLATFORM_DELAY        (3*1000LL)
 
 static void update_codec_type_and_interface(struct platform_data * my_data, const char *snd_card_name) {
 
@@ -4954,6 +4979,8 @@
              return PCM_OFFLOAD_PLATFORM_DELAY;
         case USECASE_AUDIO_PLAYBACK_ULL:
              return ULL_PLATFORM_DELAY;
+        case USECASE_AUDIO_PLAYBACK_MMAP:
+             return MMAP_PLATFORM_DELAY;
         default:
             return 0;
     }
@@ -5707,6 +5734,9 @@
         backend_cfg.format = usecase->stream.out->format;
         backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
     }
+    if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
+                (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
+        backend_cfg.bit_width = adev->dsp_bit_width_enforce_mode;
 
     /*this is populated by check_codec_backend_cfg hence set default value to false*/
     backend_cfg.passthrough_enabled = false;
@@ -6007,6 +6037,145 @@
      *length = msm_be_id_array_len;
 }
 
+int platform_set_stream_pan_scale_params(void *platform,
+                                         int snd_id,
+                                         struct mix_matrix_params mm_params)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    struct mixer_ctl *ctl = NULL;
+    char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+    int ret = 0;
+    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;
+    }
+
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                          "Audio Stream %d Pan Scale Control", snd_id);
+    ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);
+
+    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);
+        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[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    pan_scale_data[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+    pan_scale_data[length++] = 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];
+
+    ret = mixer_ctl_set_array(ctl, pan_scale_data, length);
+end:
+    return ret;
+}
+
+int platform_set_stream_downmix_params(void *platform,
+                                       int snd_id,
+                                       snd_device_t snd_device,
+                                       struct mix_matrix_params mm_params)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    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};
+    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);
+
+    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);
+        ret = -EINVAL;
+    }
+
+    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;
+
+    downmix_param_data[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    downmix_param_data[length++] = 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 {
+        ret = -EINVAL;
+        goto end;
+    }
+
+    downmix_param_data[length++] = 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];
+
+    ret = mixer_ctl_set_array(ctl, downmix_param_data, length);
+end:
+    return ret;
+}
+
 int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask,
                                                int snd_id, uint8_t *input_channel_map)
 {
@@ -7000,3 +7169,40 @@
 
     return MAX_CODEC_BACKENDS;
 }
+
+#if defined (PLATFORM_MSM8998) || (PLATFORM_SDM845)
+int platform_get_mmap_data_fd(void *platform, int fe_dev, int dir, int *fd,
+                              uint32_t *size)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    int hw_fd = -1;
+    char dev_name[128];
+    struct snd_pcm_mmap_fd mmap_fd;
+    memset(&mmap_fd, 0, sizeof(mmap_fd));
+    mmap_fd.dir = dir;
+    snprintf(dev_name, sizeof(dev_name), "/dev/snd/hwC%uD%u",
+             adev->snd_card, HWDEP_FE_BASE+fe_dev);
+    hw_fd = open(dev_name, O_RDONLY);
+    if (hw_fd < 0) {
+        ALOGE("fe hw dep node open %d/%d failed", adev->snd_card, fe_dev);
+        return -1;
+    }
+    if (ioctl(hw_fd, SNDRV_PCM_IOCTL_MMAP_DATA_FD, &mmap_fd) < 0) {
+        ALOGE("fe hw dep node ioctl failed");
+        close(hw_fd);
+        return -1;
+    }
+    *fd = mmap_fd.fd;
+    *size = mmap_fd.size;
+    close(hw_fd); // mmap_fd should still be valid
+    return 0;
+}
+#else
+int platform_get_mmap_data_fd(void *platform __unused, int fe_dev __unused,
+                              int dir __unused, int *fd __unused,
+                              uint32_t *size __unused)
+{
+    return -1;
+}
+#endif
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 06f2cdc..f4d60c2 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -385,6 +385,8 @@
 #define EC_REF_RX "I2S_RX"
 #else
 #define LOWLATENCY_PCM_DEVICE 15
+#define MMAP_PLAYBACK_PCM_DEVICE 18
+#define MMAP_RECORD_PCM_DEVICE 18
 #define EC_REF_RX "SLIM_RX"
 #endif
 
@@ -463,6 +465,15 @@
 #define TRANSCODE_LOOPBACK_RX_DEV_ID 43
 #define TRANSCODE_LOOPBACK_TX_DEV_ID 44
 
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE1 0
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE2 1
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE3 27
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE4 45
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE5 46
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE6 47
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE7 48
+#define PLAYBACK_INTERACTIVE_STRM_DEVICE8 49
+
 #ifdef PLATFORM_APQ8084
 #define FM_RX_VOLUME "Quat MI2S FM RX Volume"
 #elif PLATFORM_MSM8994
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 3c31c56..6f8cf7e 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -169,6 +169,13 @@
                              int snd_id);
 int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask,
                                    int snd_id, uint8_t *input_channel_map);
+int platform_set_stream_pan_scale_params(void *platform,
+                                         int snd_id,
+                                         struct mix_matrix_params mm_params);
+int platform_set_stream_downmix_params(void *platform,
+                                       int snd_id,
+                                       snd_device_t snd_device,
+                                       struct mix_matrix_params mm_params);
 int platform_set_edid_channels_configuration(void *platform, int channels);
 unsigned char platform_map_to_edid_format(int format);
 bool platform_is_edid_supported_format(void *platform, int format);
@@ -230,4 +237,6 @@
 void platform_check_and_update_copp_sample_rate(void *platform, snd_device_t snd_device,
      unsigned int stream_sr,int *sample_rate);
 int platform_get_max_codec_backend();
+int platform_get_mmap_data_fd(void *platform, int dev, int dir,
+                               int *fd, uint32_t *size);
 #endif // AUDIO_PLATFORM_API_H
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 0fdd136..e27214b 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -104,10 +104,12 @@
 LOCAL_MODULE:= libvolumelistener
 LOCAL_VENDOR_MODULE := true
 
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
 LOCAL_C_INCLUDES := \
         hardware/qcom/audio/hal \
         $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
-	$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/techpack/audio/include \
+        $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/techpack/audio/include \
         external/tinyalsa/include \
         $(call include-path-for, audio-effects) \
         $(call include-path-for, audio-route) \
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 635fe23..a8c2c53 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -677,7 +677,7 @@
 
     // check system property to see if dumping is required
     char check_dump_val[PROPERTY_VALUE_MAX];
-    property_get("audio.volume.listener.dump", check_dump_val, "0");
+    property_get("vendor.audio.volume.listener.dump", check_dump_val, "0");
     if (atoi(check_dump_val)) {
         dumping_enabled = true;
     }
diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h
index 23e51cb..fa780bd 100644
--- a/qahw_api/inc/qahw_defs.h
+++ b/qahw_api/inc/qahw_defs.h
@@ -177,6 +177,9 @@
 /* Query if a2dp  is supported */
 #define QAHW_PARAMETER_KEY_HANDLE_A2DP_DEVICE "isA2dpDeviceSupported"
 
+#define MAX_OUT_CHANNELS 8
+#define MAX_INP_CHANNELS 8
+
 /* type of asynchronous write callback events. Mutually exclusive */
 typedef enum {
     QAHW_STREAM_CBK_EVENT_WRITE_READY, /* non blocking write completed */
@@ -323,6 +326,17 @@
    uint16_t   channel_allocation;
 };
 
+typedef struct qahw_mix_matrix_params {
+    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];
+    uint8_t has_input_channel_map;
+    uint32_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;
+
 typedef union {
     struct qahw_source_tracking_param st_params;
     struct qahw_sound_focus_param sf_params;
@@ -335,6 +349,7 @@
     struct qahw_adsp_event adsp_event_params;
     struct qahw_out_channel_map_param channel_map_params;
     struct qahw_device_cfg_param device_cfg_params;
+    struct qahw_mix_matrix_params mix_matrix_params;
 } qahw_param_payload;
 
 typedef enum {
@@ -350,7 +365,9 @@
     QAHW_PARAM_OUT_CORRECT_DRIFT,
     QAHW_PARAM_ADSP_STREAM_CMD,
     QAHW_PARAM_OUT_CHANNEL_MAP,    /* PARAM to set i/p channel map */
-    QAHW_PARAM_DEVICE_CONFIG      /* PARAM to set device config */
+    QAHW_PARAM_DEVICE_CONFIG,      /* PARAM to set device config */
+    QAHW_PARAM_OUT_MIX_MATRIX_PARAMS,
+    QAHW_PARAM_CH_MIX_MATRIX_PARAMS,
 } qahw_param_id;
 
 __END_DECLS
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index db189eb..3c986bd 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -22,6 +22,7 @@
 #include <pthread.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
@@ -52,7 +53,7 @@
 #define FORMAT_PCM 1
 #define WAV_HEADER_LENGTH_MAX 46
 
-#define MAX_PLAYBACK_STREAMS   3
+#define MAX_PLAYBACK_STREAMS   9
 #define PRIMARY_STREAM_INDEX   0
 
 #define KVPAIRS_MAX 100
@@ -194,6 +195,7 @@
     pthread_mutex_t write_lock;
     pthread_cond_t drain_cond;
     pthread_mutex_t drain_lock;
+    bool interactive_strm;
 }stream_config;
 
 /* Lock for dual main usecase */
@@ -263,6 +265,9 @@
 #define AUDIO_OUTPUT_FLAG_ASSOCIATED 0x8000
 #endif
 
+#ifndef AUDIO_OUTPUT_FLAG_INTERACTIVE
+#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x40000
+#endif
 
 static bool request_wake_lock(bool wakelock_acquired, bool enable)
 {
@@ -683,6 +688,12 @@
             fprintf(log_file, "stream %d: after the dual main signal\n", params->stream_index);
             pthread_mutex_unlock(&dual_main_lock);
     }
+
+    if (params->interactive_strm) {
+        params->flags = AUDIO_OUTPUT_FLAG_INTERACTIVE;
+        fprintf(stderr, "stream %s %d: Interactive stream\n", __func__, params->stream_index);
+    }
+
     rc = qahw_open_output_stream(params->qahw_out_hal_handle,
                              params->handle,
                              params->output_device,
@@ -1066,7 +1077,10 @@
     int rc = 0;
 
     if (!(stream_info->flags_set)) {
-        stream_info->flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+        if (stream_info->interactive_strm)
+            stream_info->flags = AUDIO_OUTPUT_FLAG_INTERACTIVE;
+        else
+            stream_info->flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING;
         stream_info->flags |= AUDIO_OUTPUT_FLAG_DIRECT;
     }
 
@@ -1458,6 +1472,10 @@
     else
         direction = PCM_OUT;
 
+    if (direction == PCM_OUT && stream->interactive_strm) {
+        stream->flags = AUDIO_OUTPUT_FLAG_INTERACTIVE;
+        fprintf(stderr, "stream %d: Interactive stream\n", stream->stream_index);
+    }
     fprintf(log_file, "%s: opening %s stream\n", __func__, ((direction == PCM_IN)? "input":"output"));
 
     if (PCM_IN == direction)
@@ -1595,6 +1613,10 @@
     printf(" -m  --mode                                - usb operating mode(Device Mode is default)\n");
     printf("                                             0:Device Mode(host drives the stream and its params and so no need to give params as input)\n");
     printf("                                             1:Host Mode(user can give stream and stream params via a stream(SD card file) or setup loopback with given params\n");
+    printf(" -O  --output-ch-map                       - output channel map");
+    printf(" -I  --input-ch-map                        - input channel map");
+    printf(" -M  --mixer-coeffs                        - mixer coefficient matrix");
+    printf(" -i  --intr-strm                           - interactive stream indicator");
     printf(" \n Examples \n");
     printf(" hal_play_test -f /data/Anukoledenadu.wav  -> plays Wav stream with default params\n\n");
     printf(" hal_play_test -f /data/MateRani.mp3 -t 2 -d 2 -v 0.01 -r 44100 -c 2 \n");
@@ -1852,15 +1874,146 @@
     return 1;
 }
 
+audio_channel_mask_t get_channel_mask_for_name(char *name) {
+    audio_channel_mask_t channel_type = AUDIO_CHANNEL_INVALID;
+    if (NULL == name)
+        return channel_type;
+    else if (strncmp(name, "fl", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_FRONT_LEFT;
+    else if (strncmp(name, "fr", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_FRONT_RIGHT;
+    else if (strncmp(name, "fc", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_FRONT_CENTER;
+    else if (strncmp(name, "lfe", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+    else if (strncmp(name, "bl", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_BACK_LEFT;
+    else if (strncmp(name, "br", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_BACK_RIGHT;
+    else if (strncmp(name, "flc", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+    else if (strncmp(name, "frc", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+    else if (strncmp(name, "bc", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_BACK_CENTER;
+    else if (strncmp(name, "sl", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_SIDE_LEFT;
+    else if (strncmp(name, "sr", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_SIDE_RIGHT;
+    else if (strncmp(name, "tc", 2) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_CENTER;
+    else if (strncmp(name, "tfl", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT;
+    else if (strncmp(name, "tfc", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER;
+    else if (strncmp(name, "tfr", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT;
+    else if (strncmp(name, "tbl", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_BACK_LEFT;
+    else if (strncmp(name, "tbc", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_BACK_CENTER;
+    else if (strncmp(name, "tbr", 3) == 0)
+        channel_type = AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT;
+
+    return channel_type;
+}
+
+int extract_channel_mapping(uint32_t *channel_map, const char * arg_string){
+
+    char *token_string = NULL;
+    char *init_ptr = NULL;
+    char *token = NULL;
+    char *saveptr = NULL;
+
+    if (NULL == channel_map)
+        return -EINVAL;
+
+    if (NULL == arg_string)
+        return EINVAL;
+
+    token_string = strdup(arg_string);
+
+    if(token_string != NULL) {
+        init_ptr = token_string;
+        token = strtok_r(token_string, ",", &saveptr);
+        int index = 0;
+        if (NULL == token)
+            return -EINVAL;
+        else
+            channel_map[index++] = get_channel_mask_for_name(token);
+
+        while(NULL !=(token = strtok_r(NULL,",",&saveptr)))
+            channel_map[index++] = get_channel_mask_for_name(token);
+
+        free(init_ptr);
+        init_ptr = NULL;
+        token_string = NULL;
+    } else
+        return -EINVAL;
+    return 0;
+}
+
+int extract_mixer_coeffs(qahw_mix_matrix_params_t * mm_params, const char * arg_string){
+
+    char *token_string = NULL;
+    char *init_ptr = NULL;
+    char *token = NULL;
+    char *saveptr = NULL;
+    int i = 0;
+    int j = 0;
+
+    if (NULL == mm_params)
+        return -EINVAL;
+
+    if (NULL == arg_string)
+        return -EINVAL;
+
+    token_string = strdup(arg_string);
+
+    if(token_string != NULL) {
+        init_ptr = token_string;
+        token = strtok_r(token_string, ",", &saveptr);
+        int index = 0;
+        if (NULL == token)
+            return -EINVAL;
+        else {
+            mm_params->mixer_coeffs[i][j] = atof(token);
+            j++;
+        }
+
+        while(NULL !=(token = strtok_r(NULL,",",&saveptr))) {
+            if(j == mm_params->num_input_channels) {
+                j=0;
+                i++;
+            }
+            if(i == mm_params->num_output_channels)
+                break;
+            mm_params->mixer_coeffs[i][j++] = atof(token);
+        }
+        free(init_ptr);
+        init_ptr = NULL;
+        token_string = NULL;
+    } else
+        return -EINVAL;
+    return 0;
+}
 
 int main(int argc, char* argv[]) {
     char *ba = NULL;
+    char *temp_input_channel_map = NULL;
+    char *temp_output_channel_map = NULL;
+    char *temp_mixer_coeffs = NULL;
     qahw_param_payload payload;
     qahw_param_id param_id;
     struct qahw_aptx_dec_param aptx_params;
+    qahw_mix_matrix_params_t mm_params;
     int rc = 0;
     int i = 0;
+    int iter_i = 0;
+    int iter_j = 0;
     kpi_mode = false;
+    char mixer_ctrl_name[64] = {0};
+    int mixer_ctrl_type = 0;
     event_trigger = false;
     bool wakelock_acquired = false;
 
@@ -1899,6 +2052,11 @@
         {"effect-preset",   required_argument,    0, 'p'},
         {"effect-strength", required_argument,    0, 'S'},
         {"help",          no_argument,          0, 'h'},
+        {"output-ch-map", required_argument,    0, 'O'},
+        {"input-ch-map",  required_argument,    0, 'I'},
+        {"mixer-coeffs",  required_argument,    0, 'M'},
+        {"num-out-ch",    required_argument,    0, 'o'},
+        {"intr-strm",    required_argument,    0, 'i'},
         {0, 0, 0, 0}
     };
 
@@ -1921,7 +2079,7 @@
 
     while ((opt = getopt_long(argc,
                               argv,
-                              "-f:r:c:b:d:s:v:l:t:a:w:k:PD:KF:Ee:A:u:m:S:p:qQh",
+                              "-f:r:c:b:d:s:v:l:t:a:w:k:PD:KF:Ee:A:u:m:S:p:qQhI:O:M:o:i:",
                               long_options,
                               &option_index)) != -1) {
 
@@ -1938,6 +2096,7 @@
         case 'c':
             stream_param[i].channels = atoi(optarg);
             stream_param[i].config.channel_mask = audio_channel_out_mask_from_count(atoi(optarg));
+            mm_params.num_input_channels = stream_param[i].channels;
             break;
         case 'b':
             stream_param[i].config.offload_info.bit_width = atoi(optarg);
@@ -1962,6 +2121,9 @@
                 log_file = stdout;
             }
             break;
+        case 'i':
+            stream_param[i].interactive_strm = atoi(optarg);
+            break;
         case 't':
             stream_param[i].filetype = atoi(optarg);
             break;
@@ -1972,7 +2134,15 @@
             stream_param[i].wma_fmt_type = atoi(optarg);
             break;
         case 'k':
-            stream_param[i].kvpair_values = optarg;
+            get_kvpairs_string(optarg, "mixer_ctrl", mixer_ctrl_name);
+            if(strncmp(mixer_ctrl_name, "downmix", 7) == 0) {
+                mixer_ctrl_type = QAHW_PARAM_CH_MIX_MATRIX_PARAMS;
+            } else if(strncmp(mixer_ctrl_name, "pan_scale", 9) == 0) {
+                mixer_ctrl_type = QAHW_PARAM_OUT_MIX_MATRIX_PARAMS;
+            } else {
+                mixer_ctrl_type = 0;
+                stream_param[i].kvpair_values = optarg;
+            }
             break;
         case 'D':
             proxy_params.acp.file_name = optarg;
@@ -2033,6 +2203,18 @@
         case 'm':
             stream_param[i].usb_mode = atoi(optarg);
             break;
+        case 'O':
+            temp_output_channel_map = strdup(optarg);
+            break;
+        case 'I':
+            temp_input_channel_map = strdup(optarg);
+            break;
+        case 'M':
+            temp_mixer_coeffs = strdup(optarg);
+            break;
+        case 'o':
+            mm_params.num_output_channels = atoi(optarg);
+            break;
         case 'h':
             usage();
             return 0;
@@ -2041,6 +2223,49 @@
         }
     }
 
+    /*
+     * Process Input channel map's input
+     */
+    if (NULL != temp_input_channel_map) {
+        extract_channel_mapping(mm_params.input_channel_map, temp_input_channel_map);
+        mm_params.has_input_channel_map = 1;
+        fprintf(log_file, "\nInput channel mapping: ");
+        for (iter_i= 0; iter_i < mm_params.num_input_channels; iter_i++) {
+            fprintf(log_file, "0x%x, ", mm_params.input_channel_map[iter_i]);
+        }
+        free(temp_input_channel_map);
+        temp_input_channel_map = NULL;
+    }
+
+    /*
+     * Process Output channel map's input
+     */
+    if (NULL != temp_output_channel_map) {
+        extract_channel_mapping(mm_params.output_channel_map, temp_output_channel_map);
+        mm_params.has_output_channel_map = 1;
+        fprintf(log_file, "\nOutput channel mapping: ");
+        for (iter_i = 0; iter_i < mm_params.num_output_channels; iter_i++)
+            fprintf(log_file, "0x%x, ", mm_params.output_channel_map[iter_i]);
+
+        free(temp_output_channel_map);
+        temp_output_channel_map = NULL;
+    }
+
+    /*
+     * Process mixer-coeffs input
+     */
+    if (NULL != temp_mixer_coeffs) {
+        extract_mixer_coeffs(&mm_params, temp_mixer_coeffs);
+        mm_params.has_mixer_coeffs = 1;
+        fprintf(log_file, "\nmixer coeffs:\n");
+        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++){
+                fprintf(log_file, "%.2f ",mm_params.mixer_coeffs[iter_i][iter_j]);
+            }
+            fprintf(log_file, "\n");
+        }
+    }
+
     wakelock_acquired = request_wake_lock(wakelock_acquired, true);
     num_of_streams = i+1;
     /* Caution: Below ADL log shouldnt be altered without notifying automation APT since it used
@@ -2085,7 +2310,7 @@
     for (i = 0; i < num_of_streams; i++) {
         stream = &stream_param[i];
 
-        if ((kpi_mode == false) && 
+        if ((kpi_mode == false) &&
             (AUDIO_DEVICE_NONE == stream->input_device)){
             if (stream_param[PRIMARY_STREAM_INDEX].filename == nullptr) {
                 fprintf(log_file, "Primary file name is must for non kpi-mode\n");
@@ -2189,7 +2414,6 @@
             fprintf(log_file, "stream %d: play_later = %d\n", i, stream_param[i].play_later);
         }
 
-
         rc = pthread_create(&playback_thread[i], NULL, start_stream_playback, (void *)&stream_param[i]);
         if (rc) {
             fprintf(log_file, "stream %d: failed to create thread\n", stream->stream_index);
@@ -2198,7 +2422,23 @@
         }
 
         thread_active[i] = true;
-
+        usleep(500000); //Wait until stream is created
+        if(mixer_ctrl_type == QAHW_PARAM_OUT_MIX_MATRIX_PARAMS) {
+            payload = (qahw_param_payload) mm_params;
+            param_id = QAHW_PARAM_OUT_MIX_MATRIX_PARAMS;
+            rc = qahw_out_set_param_data(stream->out_handle, param_id, &payload);
+            if (rc != 0) {
+                fprintf(log_file, "QAHW_PARAM_OUT_MIX_MATRIX_PARAMS could not be sent!\n");
+            }
+        }
+        if(mixer_ctrl_type == QAHW_PARAM_CH_MIX_MATRIX_PARAMS) {
+            payload = (qahw_param_payload) mm_params;
+            param_id = QAHW_PARAM_CH_MIX_MATRIX_PARAMS;
+            rc = qahw_out_set_param_data(stream->out_handle, param_id, &payload);
+            if (rc != 0) {
+                fprintf(log_file, "QAHW_PARAM_CH_MIX_MATRIX_PARAMS could not be sent!\n");
+            }
+        }
     }
 
 exit: