Merge "For msm8996, add dep on sound_trigger.primary_headers" am: 60e731fa9f am: e5d19bc0f1
am: dcc2839851

Change-Id: I04be734a7b1ea3e3346823901175c83f024728f7
diff --git a/hal/Android.mk b/hal/Android.mk
index 7a12651..7a006e9 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -156,6 +156,8 @@
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_CFLAGS += -Werror
+
 include $(BUILD_SHARED_LIBRARY)
 
 endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 0a5bccb..b90fda0 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -44,6 +44,7 @@
 #include <hardware/audio_effect.h>
 #include <hardware/audio_alsaops.h>
 #include <system/thread_defs.h>
+#include <tinyalsa/asoundlib.h>
 #include <audio_effects/effect_aec.h>
 #include <audio_effects/effect_ns.h>
 #include "audio_hw.h"
@@ -83,6 +84,13 @@
 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)
+
+
 /* This constant enables extended precision handling.
  * TODO The flag is off until more testing is done.
  */
@@ -135,6 +143,19 @@
     .avail_min = 0,
 };
 
+struct pcm_config pcm_config_mmap_playback = {
+    .channels = DEFAULT_CHANNEL_COUNT,
+    .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 = DEFAULT_CHANNEL_COUNT,
     .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
@@ -156,6 +177,19 @@
     .avail_min = ULL_PERIOD_SIZE, //1 ms
 };
 
+struct pcm_config pcm_config_mmap_capture = {
+    .channels = DEFAULT_CHANNEL_COUNT,
+    .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
 
@@ -194,9 +228,11 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
     [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
     [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
+    [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
 
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
+    [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
 
     [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
     [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
@@ -1276,60 +1312,72 @@
 
     select_devices(adev, in->usecase);
 
-    ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
-          __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
-
-    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;
-    }
-
-    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) {
-                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;
+            ALOGE("%s: pcm stream not ready", __func__);
+            goto error_open;
         }
-        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;
-    }
-    if (in->realtime) {
         ret = pcm_start(in->pcm);
         if (ret < 0) {
-            ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
+            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;
         }
+        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;
+                goto error_open;
+            }
+        }
     }
     register_in_stream(in);
     audio_extn_perf_lock_release();
     ALOGV("%s: exit", __func__);
 
-    return ret;
+    return 0;
 
 error_open:
     stop_input_stream(in);
@@ -1667,7 +1715,35 @@
 
     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 (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+        out->pcm = NULL;
+        out->compr = compress_open(adev->snd_card, out->pcm_device_id,
+                                   COMPRESS_IN, &out->compr_config);
+        if (out->compr && !is_compress_ready(out->compr)) {
+            ALOGE("%s: %s", __func__, compress_get_error(out->compr));
+            compress_close(out->compr);
+            out->compr = NULL;
+            ret = -EIO;
+            goto error_open;
+        }
+        if (out->offload_callback)
+            compress_nonblock(out->compr, out->non_blocking);
+
+        if (adev->visualizer_start_output != NULL)
+            adev->visualizer_start_output(out->handle, out->pcm_device_id);
+        if (adev->offload_effects_start_output != NULL)
+            adev->offload_effects_start_output(out->handle, out->pcm_device_id);
+    } else 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 {
         unsigned int flags = PCM_OUT;
         unsigned int pcm_open_retry_count = 0;
 
@@ -1707,33 +1783,14 @@
                 goto error_open;
             }
         }
-    } else {
-        out->pcm = NULL;
-        out->compr = compress_open(adev->snd_card, out->pcm_device_id,
-                                   COMPRESS_IN, &out->compr_config);
-        if (out->compr && !is_compress_ready(out->compr)) {
-            ALOGE("%s: %s", __func__, compress_get_error(out->compr));
-            compress_close(out->compr);
-            out->compr = NULL;
-            ret = -EIO;
-            goto error_open;
-        }
-        if (out->offload_callback)
-            compress_nonblock(out->compr, out->non_blocking);
-
-        if (adev->visualizer_start_output != NULL)
-            adev->visualizer_start_output(out->handle, out->pcm_device_id);
-        if (adev->offload_effects_start_output != NULL)
-            adev->offload_effects_start_output(out->handle, out->pcm_device_id);
-    }
-    ret = 0;
-    if (out->realtime) {
-        ret = pcm_start(out->pcm);
-        if (ret < 0) {
-            ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
-            pcm_close(out->pcm);
-            out->pcm = NULL;
-            goto error_open;
+        if (out->realtime) {
+            ret = pcm_start(out->pcm);
+            if (ret < 0) {
+                ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
+                pcm_close(out->pcm);
+                out->pcm = NULL;
+                goto error_open;
+            }
         }
     }
     register_out_stream(out);
@@ -1741,7 +1798,7 @@
     audio_extn_tfa_98xx_enable_speaker();
 
     ALOGV("%s: exit", __func__);
-    return ret;
+    return 0;
 error_open:
     audio_extn_perf_lock_release();
     stop_output_stream(out);
@@ -1856,6 +1913,7 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
     struct audio_device *adev = out->dev;
+    bool do_stop = true;
 
     ALOGV("%s: enter: usecase(%d: %s)", __func__,
           out->usecase, use_case_table[out->usecase]);
@@ -1864,7 +1922,6 @@
     if (!out->standby) {
         if (adev->adm_deregister_stream)
             adev->adm_deregister_stream(adev->adm_data, out->handle);
-
         pthread_mutex_lock(&adev->lock);
         out->standby = true;
         if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -1872,6 +1929,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 {
             stop_compressed_output_l(out);
             out->gapless_mdata.encoder_delay = 0;
@@ -1881,7 +1942,9 @@
                 out->compr = NULL;
             }
         }
-        stop_output_stream(out);
+        if (do_stop) {
+            stop_output_stream(out);
+        }
         pthread_mutex_unlock(&adev->lock);
     }
     pthread_mutex_unlock(&out->lock);
@@ -2111,7 +2174,8 @@
 
     if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
         return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
-    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
         period_ms = (out->af_period_multiplier * out->config.period_size *
@@ -2200,39 +2264,18 @@
 
 #ifdef NO_AUDIO_OUT
 static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
-                                       const void *buffer, size_t bytes)
+                                       const void *buffer __unused, size_t bytes)
 {
     struct stream_out *out = (struct stream_out *)stream;
-    struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
-    int64_t now;
-    int64_t elapsed_time_since_last_write = 0;
-    int64_t sleep_time;
 
-    clock_gettime(CLOCK_MONOTONIC, &t);
-    now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
-
+    /* No Output device supported other than BT for playback.
+     * Sleep for the amount of buffer duration
+     */
     lock_output_stream(out);
-    if (out->last_write_time_us)
-        elapsed_time_since_last_write = now - out->last_write_time_us;
-    sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
-               out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
-    if (sleep_time > 0) {
-        usleep(sleep_time);
-    } else {
-        // we don't sleep when we exit standby (this is typical for a real alsa buffer).
-        sleep_time = 0;
-    }
-    out->last_write_time_us = now + sleep_time;
+    usleep(bytes * 1000000 / audio_stream_out_frame_size(
+            (const struct audio_stream_out *)&out->stream) /
+            out_get_sample_rate(&out->stream.common));
     pthread_mutex_unlock(&out->lock);
-    // last_write_time_us is an approximation of when the (simulated) alsa
-    // buffer is believed completely full. The usleep above waits for more space
-    // in the buffer, but by the end of the sleep the buffer is considered
-    // topped-off.
-    //
-    // On the subsequent out_write(), we measure the elapsed time spent in
-    // the mixer. This is subtracted from the sleep estimate based on frames,
-    // thereby accounting for drain in the alsa buffer during mixing.
-    // This is a crude approximation; we don't handle underruns precisely.
     return bytes;
 }
 #endif
@@ -2246,6 +2289,10 @@
     int error_code = ERROR_CODE_STANDBY;
 
     lock_output_stream(out);
+    if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
+        error_code = ERROR_CODE_WRITE;
+        goto exit;
+    }
     if (out->standby) {
         out->standby = false;
         pthread_mutex_lock(&adev->lock);
@@ -2264,7 +2311,7 @@
     }
 
     if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
+        ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
         if (out->send_new_metadata) {
             ALOGVV("send new gapless metadata");
             compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
@@ -2307,7 +2354,7 @@
             if (out->muted)
                 memset((void *)buffer, 0, bytes);
 
-            ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+            ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
 
             long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
                                                 out->config.rate;
@@ -2512,6 +2559,170 @@
     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 = "";
+
+    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;
+    info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
+
+    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 = ts2ns(&ts);
+    return 0;
+}
+
+
 /** audio_stream_in implementation **/
 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
 {
@@ -2556,6 +2767,8 @@
     struct stream_in *in = (struct stream_in *)stream;
     struct audio_device *adev = in->dev;
     int status = 0;
+    bool do_stop = true;
+
     ALOGV("%s: enter", __func__);
 
     lock_input_stream(in);
@@ -2572,13 +2785,19 @@
 
         pthread_mutex_lock(&adev->lock);
         in->standby = true;
+        if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
+            do_stop = in->capture_started;
+            in->capture_started = false;
+        }
         if (in->pcm) {
             pcm_close(in->pcm);
             in->pcm = NULL;
         }
         adev->enable_voicerx = false;
         platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
-        status = stop_input_stream(in);
+        if (do_stop) {
+            status = stop_input_stream(in);
+        }
         pthread_mutex_unlock(&adev->lock);
     }
     pthread_mutex_unlock(&in->lock);
@@ -2699,13 +2918,18 @@
     lock_input_stream(in);
 
     if (in->is_st_session) {
-        ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
+        ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
         /* Read from sound trigger HAL */
         audio_extn_sound_trigger_read(in, buffer, bytes);
         pthread_mutex_unlock(&in->lock);
         return bytes;
     }
 
+    if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
+        ret = -ENOSYS;
+        goto exit;
+    }
+
     if (in->standby) {
         pthread_mutex_lock(&adev->lock);
         ret = start_input_stream(in);
@@ -2866,6 +3090,153 @@
     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 = ts2ns(&ts);
+    return 0;
+}
+
+
 static int adev_open_output_stream(struct audio_hw_device *dev,
                                    audio_io_handle_t handle,
                                    audio_devices_t devices,
@@ -3012,8 +3383,14 @@
         } 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->usecase = USECASE_AUDIO_PLAYBACK_ULL;
             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 {
             out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
             out->config = pcm_config_low_latency;
@@ -3081,7 +3458,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() */
@@ -3108,6 +3489,7 @@
     pthread_mutex_unlock(&out->lock);
 
     *stream_out = &out->stream;
+
     ALOGV("%s: exit", __func__);
     return 0;
 
@@ -3441,37 +3823,53 @@
     } else {
         in->usecase = USECASE_AUDIO_RECORD;
         if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
-                (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
+                (in->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->config = in->realtime ? pcm_config_audio_capture_rt :
-                                  pcm_config_audio_capture;
-
-        if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
-            in->config.format = PCM_FORMAT_S24_LE;
-
-        if (!in->realtime) {
+            if (!in->realtime) {
+                in->config = pcm_config_audio_capture;
+                frame_size = audio_stream_in_frame_size(&in->stream);
+                buffer_size = get_input_buffer_size(config->sample_rate,
+                                                    config->format,
+                                                    channel_count,
+                                                   is_low_latency);
+                in->config.period_size = buffer_size / frame_size;
+                in->config.rate = config->sample_rate;
+                in->af_period_multiplier = 1;
+            } else {
+                // period size is left untouched for rt mode playback
+                in->config = pcm_config_audio_capture_rt;
+                in->af_period_multiplier = af_period_multiplier;
+            }
+        } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
+                ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 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 {
+            in->config = pcm_config_audio_capture;
             frame_size = audio_stream_in_frame_size(&in->stream);
             buffer_size = get_input_buffer_size(config->sample_rate,
                                                 config->format,
                                                 channel_count,
                                                 is_low_latency);
             in->config.period_size = buffer_size / frame_size;
-        } // period size is left untouched for rt mode playback
+            in->config.rate = config->sample_rate;
+            in->af_period_multiplier = 1;
+        }
+        if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
+            in->config.format = PCM_FORMAT_S24_LE;
     }
 
     in->config.channels = channel_count;
-    if (in->realtime) {
-        in->af_period_multiplier = af_period_multiplier;
-    } else {
-        in->config.rate = config->sample_rate;
-        in->af_period_multiplier = 1;
-    }
 
     /* This stream could be for sound trigger lab,
        get sound trigger pcm if present */
@@ -3762,6 +4160,7 @@
     adev->device.open_output_stream = adev_open_output_stream;
     adev->device.close_output_stream = adev_close_output_stream;
     adev->device.open_input_stream = adev_open_input_stream;
+
     adev->device.close_input_stream = adev_close_input_stream;
     adev->device.dump = adev_dump;
 
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 2cf72e1..b0a6282 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -71,6 +71,7 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD,
     USECASE_AUDIO_PLAYBACK_TTS,
     USECASE_AUDIO_PLAYBACK_ULL,
+    USECASE_AUDIO_PLAYBACK_MMAP,
 
     /* HFP Use case*/
     USECASE_AUDIO_HFP_SCO,
@@ -79,6 +80,7 @@
     /* Capture usecases */
     USECASE_AUDIO_RECORD,
     USECASE_AUDIO_RECORD_LOW_LATENCY,
+    USECASE_AUDIO_RECORD_MMAP,
 
     /* Voice extension usecases
      *
@@ -210,8 +212,6 @@
     card_status_t card_status;
 
     struct error_log error_log;
-
-    int64_t last_write_time_us;
 };
 
 struct stream_in {
@@ -240,6 +240,7 @@
     struct audio_device *dev;
     audio_format_t format;
     card_status_t card_status;
+    int capture_started;
 };
 
 typedef enum usecase_type_t {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 4995bd8..f7953cc 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -969,7 +969,7 @@
             ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s",
                   __func__, LIB_ACDB_LOADER);
 
-        my_data->acdb_send_audio_cal_v3 = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
+        my_data->acdb_send_audio_cal_v3 = (acdb_send_audio_cal_v3_t)dlsym(my_data->acdb_handle,
                                                     "acdb_loader_send_audio_cal_v3");
         if (!my_data->acdb_send_audio_cal_v3)
             ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
@@ -1073,7 +1073,7 @@
 {
     struct platform_data *my_data = (struct platform_data *)platform;
 
-    if (platform == NULL || device_name == NULL) {
+    if (platform == NULL) {
         ALOGW("%s: something wrong, use legacy get_snd_device name", __func__);
         strlcpy(device_name, platform_get_snd_device_name(snd_device),
                  DEVICE_NAME_MAX_SIZE);
@@ -1095,7 +1095,7 @@
 
 bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev __unused,
                                               struct audio_usecase *usecase __unused,
-                                              snd_device_t snd_device)
+                                              snd_device_t snd_device __unused)
 {
     return false;
 }
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 7b76df3..eafb64a 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1099,7 +1099,8 @@
                                       snd_device_t snd_device,
                                       char *device_name)
 {
-    device_name = platform_get_snd_device_name(snd_device);
+    strlcpy(device_name, platform_get_snd_device_name(snd_device),
+            DEVICE_NAME_MAX_SIZE);
     return 0;
 }
 
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 9d4abec..b0e87be 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -28,8 +28,8 @@
 #include "audio_extn.h"
 #include <linux/msm_audio.h>
 
-#define MIXER_XML_DEFAULT_PATH "/system/etc/mixer_paths.xml"
-#define MIXER_XML_BASE_STRING "/system/etc/mixer_paths"
+#define MIXER_XML_DEFAULT_PATH "mixer_paths.xml"
+#define MIXER_XML_BASE_STRING "mixer_paths"
 #define TOMTOM_8226_SND_CARD_NAME "msm8226-tomtom-snd-card"
 #define TOMTOM_MIXER_FILE_SUFFIX "wcd9330"
 
@@ -120,7 +120,7 @@
     bool speaker_lr_swap;
 
     void *acdb_handle;
-#if defined (PLATFORM_MSM8994) || (PLATFORM_MSM8996)
+#if defined (PLATFORM_MSM8994) || (PLATFORM_MSM8996) || (PLATFORM_MSM8998)
     acdb_init_v2_cvd_t acdb_init;
 #elif defined (PLATFORM_MSM8084)
     acdb_init_v2_t acdb_init;
@@ -158,12 +158,17 @@
                                         MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE,
                                     MULTIMEDIA3_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_MMAP] = {MMAP_PLAYBACK_PCM_DEVICE,
+            MMAP_PLAYBACK_PCM_DEVICE},
 
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE,
                               AUDIO_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
                                           LOWLATENCY_PCM_DEVICE},
 
+    [USECASE_AUDIO_RECORD_MMAP] = {MMAP_RECORD_PCM_DEVICE,
+            MMAP_RECORD_PCM_DEVICE},
+
     [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
                             VOICE_CALL_PCM_DEVICE},
     [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
@@ -499,24 +504,32 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MMAP)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {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)},
     {TO_NAME_INDEX(USECASE_QCHAT_CALL)},
     {TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
+    {TO_NAME_INDEX(USECASE_VOICEMMODE1_CALL)},
+    {TO_NAME_INDEX(USECASE_VOICEMMODE2_CALL)},
     {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
     {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
     {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
     {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
-    {TO_NAME_INDEX(USECASE_VOICEMMODE1_CALL)},
-    {TO_NAME_INDEX(USECASE_VOICEMMODE2_CALL)},
+    {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_RX)},
+    {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_AFE_PROXY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_DSM_FEEDBACK)},
 };
 
 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
-#define ULL_PLATFORM_DELAY         (7*1000LL)
+#define ULL_PLATFORM_DELAY         (3*1000LL)
+#define MMAP_PLATFORM_DELAY        (3*1000LL)
 
 static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
 static bool is_tmus = false;
@@ -974,7 +987,7 @@
         return 0;
     }
 
-#if defined (PLATFORM_MSM8994) || (PLATFORM_MSM8996)
+#if defined (PLATFORM_MSM8994) || (PLATFORM_MSM8996) || (PLATFORM_MSM8998)
     char *cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
     if (!cvd_version)
         ALOGE("failed to allocate cvd_version");
@@ -992,6 +1005,28 @@
     return 0;
 }
 
+// Treblized config files will be located in /odm/etc or /vendor/etc.
+static const char *kConfigLocationList[] =
+        {"/odm/etc", "/vendor/etc", "/system/etc"};
+static const int kConfigLocationListSize =
+        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
+
+bool resolveConfigFile(char file_name[MIXER_PATH_MAX_LENGTH]) {
+    char full_config_path[MIXER_PATH_MAX_LENGTH];
+    for (int i = 0; i < kConfigLocationListSize; i++) {
+        snprintf(full_config_path,
+                 MIXER_PATH_MAX_LENGTH,
+                 "%s/%s",
+                 kConfigLocationList[i],
+                 file_name);
+        if (F_OK == access(full_config_path, 0)) {
+            strcpy(file_name, full_config_path);
+            return true;
+        }
+    }
+    return false;
+}
+
 void *platform_init(struct audio_device *adev)
 {
     char value[PROPERTY_VALUE_MAX];
@@ -1075,15 +1110,15 @@
             snprintf(mixer_xml_file, sizeof(mixer_xml_file), "%s_%s_%s.xml",
                              MIXER_XML_BASE_STRING, snd_split_handle->snd_card,
                              snd_split_handle->form_factor);
-
-            if (F_OK != access(mixer_xml_file, 0)) {
+            if (!resolveConfigFile(mixer_xml_file)) {
                 memset(mixer_xml_file, 0, sizeof(mixer_xml_file));
                 snprintf(mixer_xml_file, sizeof(mixer_xml_file), "%s_%s.xml",
                              MIXER_XML_BASE_STRING, snd_split_handle->snd_card);
 
-                if (F_OK != access(mixer_xml_file, 0)) {
+                if (!resolveConfigFile(mixer_xml_file)) {
                     memset(mixer_xml_file, 0, sizeof(mixer_xml_file));
                     strlcpy(mixer_xml_file, MIXER_XML_DEFAULT_PATH, MIXER_PATH_MAX_LENGTH);
+                    resolveConfigFile(mixer_xml_file);
                 }
             }
 
@@ -1091,14 +1126,15 @@
                              PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
                              snd_split_handle->form_factor);
 
-            if (F_OK != access(platform_info_file, 0)) {
+            if (!resolveConfigFile(platform_info_file)) {
                 memset(platform_info_file, 0, sizeof(platform_info_file));
                 snprintf(platform_info_file, sizeof(platform_info_file), "%s_%s.xml",
                              PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
 
-                if (F_OK != access(platform_info_file, 0)) {
+                if (!resolveConfigFile(platform_info_file)) {
                     memset(platform_info_file, 0, sizeof(platform_info_file));
                     strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
+                    resolveConfigFile(platform_info_file);
                 }
             }
         }
@@ -1253,7 +1289,7 @@
             ALOGV("%s: Could not find the symbol acdb_loader_send_gain_dep_cal from %s",
                   __func__, LIB_ACDB_LOADER);
 
-#if defined (PLATFORM_MSM8994) || (PLATFORM_MSM8996)
+#if defined (PLATFORM_MSM8994) || (PLATFORM_MSM8996) || (PLATFORM_MSM8998)
         acdb_init_v2_cvd_t acdb_init;
         acdb_init = (acdb_init_v2_cvd_t)dlsym(my_data->acdb_handle,
                                               "acdb_loader_init_v2");
@@ -1366,9 +1402,10 @@
 {
     struct platform_data *my_data = (struct platform_data *)platform;
 
-    if (platform == NULL || device_name == NULL) {
+    if (platform == NULL) {
         ALOGW("%s: something wrong, use legacy get_snd_device name", __func__);
-        device_name = platform_get_snd_device_name(snd_device);
+        strlcpy(device_name, platform_get_snd_device_name(snd_device),
+                DEVICE_NAME_MAX_SIZE);
     } else if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
         if (operator_specific_device_table[snd_device] != NULL) {
             strlcpy(device_name, get_operator_specific_device_mixer_path(snd_device),
@@ -1527,8 +1564,8 @@
     return ret;
 }
 
-int platform_get_default_app_type_v2(void *platform, usecase_type_t type __unused,
-                                     int *app_type)
+int platform_get_default_app_type_v2(void *platform __unused, usecase_type_t type __unused,
+                                     int *app_type __unused)
 {
     ALOGE("%s: Not implemented", __func__);
     return -ENOSYS;
@@ -2160,10 +2197,10 @@
             } else if ((channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) &&
                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
                 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
-            } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) &&
+            } else if ((channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) &&
                        (my_data->source_mic_type & SOURCE_THREE_MIC)) {
                 snd_device = SND_DEVICE_IN_THREE_MIC;
-            } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) &&
+            } else if ((channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) &&
                        (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
                 snd_device = SND_DEVICE_IN_QUAD_MIC;
             }
@@ -2190,10 +2227,10 @@
                  (channel_mask == AUDIO_CHANNEL_IN_STEREO)) &&
                        (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
                 snd_device = SND_DEVICE_IN_UNPROCESSED_STEREO_MIC;
-            } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) &&
+            } else if ((channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) &&
                        (my_data->source_mic_type & SOURCE_THREE_MIC)) {
                 snd_device = SND_DEVICE_IN_UNPROCESSED_THREE_MIC;
-            } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) &&
+            } else if ((channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) &&
                        (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
                 snd_device = SND_DEVICE_IN_UNPROCESSED_QUAD_MIC;
             } else {
@@ -2281,10 +2318,10 @@
             !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
             if ((my_data->source_mic_type & SOURCE_QUAD_MIC) &&
-                (int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) {
+                channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) {
                 snd_device = SND_DEVICE_IN_QUAD_MIC;
             } else if ((my_data->source_mic_type & SOURCE_THREE_MIC) &&
-                       (int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) {
+                       channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) {
                 snd_device = SND_DEVICE_IN_THREE_MIC;
             } else if ((my_data->source_mic_type & SOURCE_DUAL_MIC) &&
                        channel_count == 2) {
@@ -2620,13 +2657,16 @@
             return LOW_LATENCY_PLATFORM_DELAY;
         case USECASE_AUDIO_PLAYBACK_ULL:
             return ULL_PLATFORM_DELAY;
+        case USECASE_AUDIO_PLAYBACK_MMAP:
+            return MMAP_PLATFORM_DELAY;
         default:
             return 0;
     }
 }
 
 bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev,
-         struct audio_usecase *usecase, snd_device_t snd_device)
+         struct audio_usecase *usecase __unused,
+         snd_device_t snd_device __unused)
 {
     enum pcm_format  in_pcm_format = PCM_FORMAT_S16_LE;
 
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index aa4c08d..fb6e24d 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -215,6 +215,9 @@
 
 #define MULTIMEDIA3_PCM_DEVICE 4
 
+#define MMAP_PLAYBACK_PCM_DEVICE 18
+#define MMAP_RECORD_PCM_DEVICE 18
+
 #define QUAT_MI2S_PCM_DEVICE    44
 #define PLAYBACK_OFFLOAD_DEVICE 9
 #define LOWLATENCY_PCM_DEVICE 15
@@ -313,6 +316,6 @@
     get_sample_rate_t get_sample_rate;
 };
 
-#define PLATFORM_INFO_XML_PATH          "/system/etc/audio_platform_info.xml"
-#define PLATFORM_INFO_XML_BASE_STRING   "/system/etc/audio_platform_info"
+#define PLATFORM_INFO_XML_PATH          "audio_platform_info.xml"
+#define PLATFORM_INFO_XML_BASE_STRING   "audio_platform_info"
 #endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/platform_api.h b/hal/platform_api.h
index ebbe9d2..83554b0 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -28,6 +28,7 @@
 };
 
 enum card_status_t;
+struct audio_usecase;
 enum usecase_type_t;
 
 void *platform_init(struct audio_device *adev);
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index df327ab..73b9ae5 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -244,7 +244,7 @@
 __attribute__ ((visibility ("default")))
 int offload_effects_bundle_hal_stop_output(audio_io_handle_t output, int pcm_id)
 {
-    int ret;
+    int ret = 0;
     struct listnode *node;
     struct listnode *fx_node;
     output_context_t *out_ctxt;
@@ -750,11 +750,11 @@
 
 __attribute__ ((visibility ("default")))
 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
-    tag : AUDIO_EFFECT_LIBRARY_TAG,
-    version : EFFECT_LIBRARY_API_VERSION,
-    name : "Offload Effects Bundle Library",
-    implementor : "The Android Open Source Project",
-    create_effect : effect_lib_create,
-    release_effect : effect_lib_release,
-    get_descriptor : effect_lib_get_descriptor,
+    .tag = AUDIO_EFFECT_LIBRARY_TAG,
+    .version = EFFECT_LIBRARY_API_VERSION,
+    .name = "Offload Effects Bundle Library",
+    .implementor = "The Android Open Source Project",
+    .create_effect = effect_lib_create,
+    .release_effect = effect_lib_release,
+    .get_descriptor = effect_lib_get_descriptor,
 };
diff --git a/post_proc/equalizer.c b/post_proc/equalizer.c
index 1cd40d2..c3a438f 100644
--- a/post_proc/equalizer.c
+++ b/post_proc/equalizer.c
@@ -183,7 +183,7 @@
 
 int equalizer_get_num_presets(equalizer_context_t *context __unused)
 {
-    ALOGV("%s: presets_num: %d", __func__,
+    ALOGV("%s: presets_num: %zu", __func__,
            sizeof(equalizer_preset_names)/sizeof(char *));
     return sizeof(equalizer_preset_names)/sizeof(char *);
 }
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 1402ae6..2858e04 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -366,7 +366,9 @@
             ALOGE("%s: EFFECT_CMD_INIT: %s, sending -EINVAL", __func__,
                   (p_reply_data == NULL) ? "p_reply_data is NULL" :
                   "*reply_size != sizeof(int)");
-            return -EINVAL;
+            android_errorWriteLog(0x534e4554, "32669549");
+            status = -EINVAL;
+            goto exit;
         }
         *(int *)p_reply_data = 0;
         break;
@@ -375,7 +377,9 @@
         ALOGV("%s :: cmd called EFFECT_CMD_SET_CONFIG", __func__);
         if (p_cmd_data == NULL || cmd_size != sizeof(effect_config_t)
                 || p_reply_data == NULL || reply_size == NULL || *reply_size != sizeof(int)) {
-            return -EINVAL;
+            android_errorWriteLog(0x534e4554, "32669549");
+            status = -EINVAL;
+            goto exit;
         }
         context->config = *(effect_config_t *)p_cmd_data;
         *(int *)p_reply_data = 0;
@@ -399,7 +403,9 @@
             ALOGE("%s: EFFECT_CMD_OFFLOAD: %s, sending -EINVAL", __func__,
                   (p_reply_data == NULL) ? "p_reply_data is NULL" :
                   "*reply_size != sizeof(int)");
-            return -EINVAL;
+            android_errorWriteLog(0x534e4554, "32669549");
+            status = -EINVAL;
+            goto exit;
         }
         *(int *)p_reply_data = 0;
         break;
diff --git a/visualizer/offload_visualizer.c b/visualizer/offload_visualizer.c
index c56ebff..4d1373f 100644
--- a/visualizer/offload_visualizer.c
+++ b/visualizer/offload_visualizer.c
@@ -81,11 +81,11 @@
     effect_ops_t ops;
 };
 
-typedef struct output_context_s {
+struct output_context_s {
     struct listnode outputs_list_node;  /* node in active_outputs_list */
     audio_io_handle_t handle; /* io handle */
     struct listnode effects_list; /* list of effects attached to this output */
-} output_context_t;
+};
 
 
 /* maximum time since last capture buffer update before resetting capture buffer. This means
@@ -427,7 +427,7 @@
 
 __attribute__ ((visibility ("default")))
 int visualizer_hal_start_output(audio_io_handle_t output, int pcm_id) {
-    int ret;
+    int ret = 0;
     struct listnode *node;
 
     ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
@@ -473,7 +473,7 @@
 
 __attribute__ ((visibility ("default")))
 int visualizer_hal_stop_output(audio_io_handle_t output, int pcm_id) {
-    int ret;
+    int ret = 0;
     struct listnode *node;
     struct listnode *fx_node;
     output_context_t *out_ctxt;