Merge "Initial Android target definition for trinket"
diff --git a/configs/msmnile/msmnile.mk b/configs/msmnile/msmnile.mk
index 6005bff..bfe9a2a 100644
--- a/configs/msmnile/msmnile.mk
+++ b/configs/msmnile/msmnile.mk
@@ -230,6 +230,13 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.hal.output.suspend.supported=true
 
+# Enable AAudio MMAP/NOIRQ data path.
+# 2 is AAUDIO_POLICY_AUTO so it will try MMAP then fallback to Legacy path.
+PRODUCT_PROPERTY_OVERRIDES += aaudio.mmap_policy=2
+# Allow EXCLUSIVE then fall back to SHARED.
+PRODUCT_PROPERTY_OVERRIDES += aaudio.mmap_exclusive_policy=2
+PRODUCT_PROPERTY_OVERRIDES += aaudio.hw_burst_min_usec=2000
+
 #enable mirror-link feature
 PRODUCT_PROPERTY_OVERRIDES += \
 vendor.audio.enable.mirrorlink=false
diff --git a/configs/msmsteppe/audio_policy_configuration.xml b/configs/msmsteppe/audio_policy_configuration.xml
index 5bec809..2131c39 100644
--- a/configs/msmsteppe/audio_policy_configuration.xml
+++ b/configs/msmsteppe/audio_policy_configuration.xml
@@ -182,7 +182,7 @@
                              samplingRates="8000,16000,48000"
                              channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
-                <mixPort name="surround_sound" role="sink">
+                <mixPort name="surround_sound" role="sink" maxActiveCount="2">
                     <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,AUDIO_CHANNEL_INDEX_MASK_4,AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6"/>
diff --git a/configs/msmsteppe/sound_trigger_mixer_paths_wcd9340.xml b/configs/msmsteppe/sound_trigger_mixer_paths_wcd9340.xml
index f74c4fe..1612470 100644
--- a/configs/msmsteppe/sound_trigger_mixer_paths_wcd9340.xml
+++ b/configs/msmsteppe/sound_trigger_mixer_paths_wcd9340.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_1_TX" value="0" />
+    <ctl name="LSM2 Mixer SLIMBUS_1_TX" value="0" />
+    <ctl name="LSM3 Mixer SLIMBUS_1_TX" value="0" />
+    <ctl name="LSM4 Mixer SLIMBUS_1_TX" value="0" />
+    <ctl name="LSM5 Mixer SLIMBUS_1_TX" value="0" />
+    <ctl name="LSM6 Mixer SLIMBUS_1_TX" value="0" />
+    <ctl name="LSM7 Mixer SLIMBUS_1_TX" value="0" />
+    <ctl name="LSM8 Mixer SLIMBUS_1_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_1_TX LSM Function" value="None" />
     <ctl name="MADONOFF Switch" value="0" />
     <ctl name="MAD Input" value="DMIC1" />
     <ctl name="MAD_SEL MUX" value="SPE" />
@@ -60,22 +69,22 @@
     <ctl name="EC BUF MUX INP" value="ZERO" />
     <ctl name="ADC MUX1" value="DMIC" />
     <ctl name="DMIC MUX1" value="ZERO" />
-    <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="CDC_IF TX5 MUX" value="ZERO" />
-    <ctl name="CDC_IF TX6 MUX" value="ZERO" />
-    <ctl name="CDC_IF TX7 MUX" value="ZERO" />
-    <ctl name="CDC_IF 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="AIF3_CAP Mixer SLIM TX3" value="0"/>
+    <ctl name="AIF3_CAP Mixer SLIM TX2" value="0" />
+    <ctl name="AIF3_CAP Mixer SLIM TX1" value="0" />
+    <ctl name="AIF3_CAP Mixer SLIM TX0" value="0"/>
+    <ctl name="CDC_IF TX0 MUX" value="ZERO" />
+    <ctl name="CDC_IF TX1 MUX" value="ZERO" />
+    <ctl name="CDC_IF TX2 MUX" value="ZERO" />
+    <ctl name="CDC_IF TX3 MUX" value="ZERO" />
+    <ctl name="ADC MUX0" value="AMIC" />
+    <ctl name="ADC MUX1" value="AMIC" />
+    <ctl name="ADC MUX2" value="AMIC" />
+    <ctl name="ADC MUX3" value="AMIC" />
+    <ctl name="DMIC MUX0" value="ZERO" />
+    <ctl name="DMIC MUX1" value="ZERO" />
+    <ctl name="DMIC MUX2" value="ZERO" />
+    <ctl name="DMIC MUX3" value="ZERO" />
     <ctl name="IIR0 INP0 MUX" value="ZERO" />
     <ctl name= "ADC MUX0" value="AMIC" />
     <ctl name= "ADC MUX1" value="AMIC" />
@@ -89,6 +98,11 @@
     <ctl name= "WDMA3 CH1 MUX" value="PORT_0" />
     <ctl name= "WDMA3 CH2 MUX" value="PORT_0" />
     <ctl name= "WDMA3_ON_OFF Switch" value="0" />
+    <ctl name="SLIM_1_TX Channels" value="One" />
+    <ctl name="AUDIO_REF_EC_UL1 MUX" value="None"/>
+    <ctl name="EC Reference Channels" value="Zero"/>
+    <ctl name="EC Reference Bit Format" value="0"/>
+    <ctl name="EC Reference SampleRate" value="0"/>
 
     <path name="listen-voice-wakeup-1">
         <ctl name="SLIMBUS_5_TX LSM Function" value="AUDIO" />
@@ -139,51 +153,51 @@
     </path>
 
     <path name="listen-voice-wakeup-1 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM1 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM1 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM1 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-2 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM2 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM2 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM2 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-3 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM3 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM3 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM3 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-4 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM4 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM4 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM4 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-5 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM5 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM5 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM5 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-6 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM6 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM6 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM6 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-7 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM7 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM7 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM7 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-voice-wakeup-8 preproc">
-        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="SLIMBUS_1_TX LSM Function" value="SWAUDIO" />
         <ctl name="LSM8 Port" value="ADM_LSM_TX" />
-        <ctl name="LSM8 Mixer SLIMBUS_0_TX" value="1" />
+        <ctl name="LSM8 Mixer SLIMBUS_1_TX" value="1" />
     </path>
 
     <path name="listen-cpe-handset-mic">
@@ -285,60 +299,60 @@
     </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="CDC_IF TX7 MUX" value="DEC7" />
-        <ctl name="ADC MUX7" value="DMIC" />
-        <ctl name="DMIC MUX7" value="DMIC2" />
-        <ctl name="IIR0 INP0 MUX" value="DEC7" />
+        <ctl name="AIF3_CAP Mixer SLIM TX2" value="1" />
+        <ctl name="SLIM_1_TX Channels" value="One" />
+        <ctl name="CDC_IF TX2 MUX" value="DEC2" />
+        <ctl name="ADC MUX2" value="DMIC" />
+        <ctl name="DMIC MUX2" value="DMIC2" />
+        <ctl name="IIR0 INP0 MUX" value="DEC2" />
     </path>
 
     <path name="listen-ape-handset-dmic">
-        <ctl name="AIF1_CAP Mixer SLIM TX7" value="1" />
-        <ctl name="AIF1_CAP Mixer SLIM TX8" value="1" />
-        <ctl name="CDC_IF TX7 MUX" value="DEC7" />
-        <ctl name="ADC MUX7" value="DMIC" />
-        <ctl name="DMIC MUX7" value="DMIC2" />
-        <ctl name="CDC_IF TX8 MUX" value="DEC8" />
-        <ctl name="ADC MUX8" value="DMIC" />
-        <ctl name="DMIC MUX8" value="DMIC5" />
-        <ctl name="SLIM_0_TX Channels" value="Two" />
+        <ctl name="AIF3_CAP Mixer SLIM TX2" value="1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX3" value="1" />
+        <ctl name="CDC_IF TX2 MUX" value="DEC2" />
+        <ctl name="ADC MUX2" value="DMIC" />
+        <ctl name="DMIC MUX2" value="DMIC2" />
+        <ctl name="CDC_IF TX3 MUX" value="DEC3" />
+        <ctl name="ADC MUX3" value="DMIC" />
+        <ctl name="DMIC MUX3" value="DMIC5" />
+        <ctl name="SLIM_1_TX Channels" value="Two" />
     </path>
 
     <path name="listen-ape-handset-tmic">
-        <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="SLIM_0_TX Channels" value="Three" />
-        <ctl name="CDC_IF TX5 MUX" value="DEC5" />
-        <ctl name="ADC MUX5" value="DMIC" />
-        <ctl name="DMIC MUX5" value="DMIC2" />
-        <ctl name="CDC_IF TX6 MUX" value="DEC6" />
-        <ctl name="ADC MUX6" value="DMIC" />
-        <ctl name="DMIC MUX6" value="DMIC0" />
-        <ctl name="CDC_IF TX7 MUX" value="DEC7" />
-        <ctl name="ADC MUX7" value="DMIC" />
-        <ctl name="DMIC MUX7" value="DMIC5" />
+        <ctl name="AIF3_CAP Mixer SLIM TX0" value="1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX1" value="1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX2" value="1" />
+        <ctl name="SLIM_1_TX Channels" value="Three" />
+        <ctl name="CDC_IF TX0 MUX" value="DEC0" />
+        <ctl name="ADC MUX0" value="DMIC" />
+        <ctl name="DMIC MUX0" value="DMIC2" />
+        <ctl name="CDC_IF TX1 MUX" value="DEC1" />
+        <ctl name="ADC MUX1" value="DMIC" />
+        <ctl name="DMIC MUX1" value="DMIC0" />
+        <ctl name="CDC_IF TX2 MUX" value="DEC2" />
+        <ctl name="ADC MUX2" value="DMIC" />
+        <ctl name="DMIC MUX2" value="DMIC5" />
     </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="CDC_IF TX5 MUX" value="DEC5" />
-        <ctl name="ADC MUX5" value="DMIC" />
-        <ctl name="DMIC MUX5" value="DMIC2" />
-        <ctl name="CDC_IF TX6 MUX" value="DEC6" />
-        <ctl name="ADC MUX6" value="DMIC" />
-        <ctl name="DMIC MUX6" value="DMIC0" />
-        <ctl name="CDC_IF TX7 MUX" value="DEC7" />
-        <ctl name="ADC MUX7" value="DMIC" />
-        <ctl name="DMIC MUX7" value="DMIC5" />
-        <ctl name="CDC_IF TX8 MUX" value="DEC8" />
-        <ctl name="ADC MUX8" value="DMIC" />
-        <ctl name="DMIC MUX8" value="DMIC1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX0" value="1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX1" value="1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX2" value="1" />
+        <ctl name="AIF3_CAP Mixer SLIM TX3" value="1" />
+        <ctl name="SLIM_1_TX Channels" value="Four" />
+        <ctl name="CDC_IF TX0 MUX" value="DEC0" />
+        <ctl name="ADC MUX0" value="DMIC" />
+        <ctl name="DMIC MUX0" value="DMIC2" />
+        <ctl name="CDC_IF TX1 MUX" value="DEC1" />
+        <ctl name="ADC MUX1" value="DMIC" />
+        <ctl name="DMIC MUX1" value="DMIC0" />
+        <ctl name="CDC_IF TX2 MUX" value="DEC2" />
+        <ctl name="ADC MUX2" value="DMIC" />
+        <ctl name="DMIC MUX2" value="DMIC5" />
+        <ctl name="CDC_IF TX3 MUX" value="DEC3" />
+        <ctl name="ADC MUX3" value="DMIC" />
+        <ctl name="DMIC MUX3" value="DMIC1" />
     </path>
 
     <path name="echo-reference">
@@ -348,4 +362,11 @@
         <ctl name="EC Reference SampleRate" value="48000"/>
     </path>
 
+    <path name="echo-reference a2dp">
+        <ctl name="AUDIO_REF_EC_UL1 MUX" value="SLIM_7_RX"/>
+        <ctl name="EC Reference Channels" value="Two"/>
+        <ctl name="EC Reference Bit Format" value="S16_LE"/>
+        <ctl name="EC Reference SampleRate" value="48000"/>
+    </path>
+
 </mixer>
diff --git a/configs/msmsteppe/sound_trigger_platform_info.xml b/configs/msmsteppe/sound_trigger_platform_info.xml
index 2a4d950..91e84d0 100644
--- a/configs/msmsteppe/sound_trigger_platform_info.xml
+++ b/configs/msmsteppe/sound_trigger_platform_info.xml
@@ -44,13 +44,15 @@
         <param transit_to_adsp_on_battery_charging="false" />
         <!-- Below backend params must match with port used in mixer path file -->
         <!-- param used to configure backend sample rate, format and channels -->
-        <!-- uncomment TX_CDC_DMA_TX_3 values for internal codec and comment SLIM_0_TX values -->
-        <param backend_port_name="SLIM_0_TX" />
+        <!-- uncomment TX_CDC_DMA_TX_3 values for internal codec and comment SLIM_1_TX values -->
+        <param backend_port_name="SLIM_1_TX" />
         <!-- param backend_port_name="TX_CDC_DMA_TX_3" /-->
         <!-- Param used to match and obtain device backend index -->
-        <param backend_dai_name="SLIMBUS_0_TX" />
+        <param backend_dai_name="SLIMBUS_1_TX" />
         <!-- param backend_dai_name="TX_CDC_DMA_TX_3" /-->
-
+        <!-- Param used to indicate if SVA has dedicated SLIM ports -->
+        <!-- Set to false for platforms with internal codec -->
+        <param dedicated_sva_path="true" />
     </common_config>
     <acdb_ids>
         <!--For internal codec please enable below device-->
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index d7f57fa..640c5f5 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -89,6 +89,7 @@
 /*DIRECT PCM has same buffer sizes as DEEP Buffer*/
 #define DIRECT_PCM_NUM_FRAGMENTS 2
 #define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
 #define VOIP_PLAYBACK_VOLUME_MAX 0x2000
 #define DSD_VOLUME_MIN_DB (-110)
 
@@ -444,6 +445,7 @@
 
 static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
 static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
+static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
 static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
 
 static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
@@ -1299,9 +1301,10 @@
         if (platform_check_backends_match(d3[0], d3[1])) {
             return d2; // case 5
         } else {
-            // check if d1 is related to any of d3's
-            if (d1 == d3[0] || d1 == d3[1])
-                return d1; // case 1
+            // check if d1 is related to any of d3's OR
+            // old uc is combo device but new_uc is one of the combo device
+            if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
+                return d1; // case 1, 7
             else
                 return d3[1]; // case 8
         }
@@ -3111,6 +3114,7 @@
           __func__, adev->snd_card, out->pcm_device_id, out->config.format);
 
     if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
+        ALOGD("%s: Starting MMAP stream", __func__);
         if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
             ALOGE("%s: pcm stream not ready", __func__);
             goto error_open;
@@ -3120,6 +3124,7 @@
             ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
             goto error_open;
         }
+        out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
     } else if (!is_offload_usecase(out->usecase)) {
         unsigned int flags = PCM_OUT;
         unsigned int pcm_open_retry_count = 0;
@@ -4269,6 +4274,38 @@
     return db;
 }
 
+static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
+                          float right)
+{
+    struct stream_out *out = (struct stream_out *)stream;
+    long volume = 0;
+    char mixer_ctl_name[128] = "";
+    struct audio_device *adev = out->dev;
+    struct mixer_ctl *ctl = NULL;
+    int pcm_device_id = platform_get_pcm_device_id(out->usecase,
+                                               PCM_PLAYBACK);
+
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+             "Playback %d Volume", pcm_device_id);
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+              __func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+    if (left != right)
+        ALOGW("%s: Left and right channel volume mismatch:%f,%f",
+                 __func__, left, right);
+    volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
+    if (mixer_ctl_set_value(ctl, 0, volume) < 0){
+        ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
+           __func__, mixer_ctl_name, volume);
+        return -EINVAL;
+    }
+    return 0;
+}
+
+
 static int out_set_compr_volume(struct audio_stream_out *stream, float left,
                           float right)
 {
@@ -4329,6 +4366,8 @@
     int volume[2];
     int ret = 0;
 
+    ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
+
     if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
         /* only take left channel into account: the API is for stereo anyway */
         out->muted = (left == 0.0f);
@@ -4357,7 +4396,7 @@
             return 0;
         } else {
             pthread_mutex_lock(&out->compr_mute_lock);
-            ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
+            ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
             if (!out->a2dp_compress_mute)
                 ret = out_set_compr_volume(stream, left, right);
             out->volume_l = left;
@@ -4371,6 +4410,13 @@
         out->volume_l = left;
         out->volume_r = right;
         return ret;
+    } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
+        ALOGV("%s: MMAP set volume called", __func__);
+        if (!out->standby)
+            ret = out_set_mmap_volume(stream, left, right);
+        out->volume_l = left;
+        out->volume_r = right;
+        return ret;
     }
 
     return -ENOSYS;
@@ -5064,8 +5110,9 @@
     unsigned int frames1 = 0;
     const char *step = "";
     uint32_t mmap_size;
+    uint32_t buffer_size;
 
-    ALOGV("%s", __func__);
+    ALOGD("%s", __func__);
     pthread_mutex_lock(&adev->lock);
 
     if (info == NULL || min_size_frames == 0) {
@@ -5088,7 +5135,7 @@
 
     adjust_mmap_period_count(&out->config, min_size_frames);
 
-    ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
+    ALOGD("%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);
@@ -5103,17 +5150,24 @@
         goto exit;
     }
     info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
+    buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
     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;
+        // Fall back to non exclusive mode
+        info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
+    } else {
+        if (mmap_size < buffer_size) {
+            step = "mmap";
+            goto exit;
+        }
+        // FIXME: indicate exclusive mode support by returning a negative buffer size
+        info->buffer_size_frames *= -1;
     }
-    memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
-                                                               info->buffer_size_frames));
+    memset(info->shared_memory_address, 0, buffer_size);
 
     ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
     if (ret < 0) {
@@ -5124,7 +5178,7 @@
     out->standby = false;
     ret = 0;
 
-    ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
+    ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
           __func__, info->shared_memory_address, info->buffer_size_frames);
 
 exit:
@@ -5253,15 +5307,15 @@
                 audio_extn_cin_stop_input_stream(in);
         }
 
-        if (do_stop) {
-            if (in->pcm) {
+        if (in->pcm) {
                 ATRACE_BEGIN("pcm_in_close");
                 pcm_close(in->pcm);
                 ATRACE_END();
                 in->pcm = NULL;
-            }
-            status = stop_input_stream(in);
         }
+
+        if (do_stop)
+            status = stop_input_stream(in);
         pthread_mutex_unlock(&adev->lock);
     }
     pthread_mutex_unlock(&in->lock);
@@ -5669,6 +5723,8 @@
     unsigned int offset1 = 0;
     unsigned int frames1 = 0;
     const char *step = "";
+    uint32_t mmap_size = 0;
+    uint32_t buffer_size = 0;
 
     pthread_mutex_lock(&adev->lock);
     ALOGV("%s in %p", __func__, in);
@@ -5709,12 +5765,27 @@
         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));
+    info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
+    buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
+    info->burst_size_frames = in->config.period_size;
+    ret = platform_get_mmap_data_fd(adev->platform,
+                                    in->pcm_device_id, 1 /*capture*/,
+                                    &info->shared_memory_fd,
+                                    &mmap_size);
+    if (ret < 0) {
+        // Fall back to non exclusive mode
+        info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
+    } else {
+        if (mmap_size < buffer_size) {
+            step = "mmap";
+            goto exit;
+        }
+        // FIXME: indicate exclusive mode support by returning a negative buffer size
+        info->buffer_size_frames *= -1;
+    }
+
+    memset(info->shared_memory_address, 0, buffer_size);
 
     ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
     if (ret < 0) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 4626fb8..63c3b90 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -3246,7 +3246,12 @@
         snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED ||
         snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT ||
         snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_RAS ||
-        snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT_RAS) {
+        snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT_RAS ||
+        snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+        snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_WSA ||
+        snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
+        snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED ||
+        snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT ) {
         ret = true;
     }
     return ret;
@@ -6236,6 +6241,9 @@
         }
     }
 
+    if (!(hw_info_is_stereo_spkr(my_data->hw_info)) && check_snd_device_is_speaker(snd_device))
+        channels = 1;
+
     /* Native playback is preferred for Headphone/HS device over 192Khz */
     if (!voice_call_active && codec_device_supports_native_playback(usecase->devices)) {
         if (audio_is_true_native_stream_active(adev)) {
@@ -6375,6 +6383,7 @@
     // Force routing if the expected bitwdith or samplerate
     // is not same as current backend comfiguration
     if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
+        (channels != my_data->current_backend_cfg[backend_idx].channels) ||
         (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate) ||
          passthrough_enabled || channels_updated || service_interval_update ) {
         backend_cfg->bit_width = bit_width;
@@ -6432,12 +6441,7 @@
         backend_cfg.bit_width = usecase->stream.out->bit_width;
         backend_cfg.sample_rate = usecase->stream.out->sample_rate;
         backend_cfg.format = usecase->stream.out->format;
-        if (!(hw_info_is_stereo_spkr(my_data->hw_info)) &&
-             check_snd_device_is_speaker(snd_device))
-            backend_cfg.channels = 1;
-        else
-            backend_cfg.channels =
-                audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
+        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))