audio: update feature files

Update the source files for ma_listener, cirrus_playback and
maxxaudio to latest versions.

CRs-Fixed: 2388992
Change-Id: I62eecf0356ee942d085ee94b848225a91704e688
diff --git a/hal/Android.mk b/hal/Android.mk
index c344898..9485d6b 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -215,11 +215,6 @@
   LOCAL_CFLAGS += -DBG_CODEC_CAL
 endif
 
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_CIRRUS_SPKR_PROTECTION)),true)
-    LOCAL_CFLAGS += -DSPKR_PROT_ENABLED
-    LOCAL_SRC_FILES += audio_extn/cirrus_playback.c
-endif
-
 ifdef MULTIPLE_HW_VARIANTS_ENABLED
   LOCAL_CFLAGS += -DHW_VARIANTS_ENABLED
   LOCAL_SRC_FILES += $(AUDIO_PLATFORM)/hw_info.c
@@ -493,11 +488,6 @@
     LOCAL_SRC_FILES += audio_extn/sndmonitor.c
 endif
 
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MAXX_AUDIO)), true)
-    LOCAL_CFLAGS += -DMAXXAUDIO_QDSP_ENABLED
-    LOCAL_SRC_FILES += audio_extn/maxxaudio.c
-endif
-
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_GCOV)),true)
     LOCAL_CFLAGS += --coverage -fprofile-arcs -ftest-coverage
     LOCAL_CPPFLAGS += --coverage -fprofile-arcs -ftest-coverage
diff --git a/hal/audio_extn/cirrus_playback.c b/hal/audio_extn/cirrus_playback.c
index c93e2e8..25fe258 100644
--- a/hal/audio_extn/cirrus_playback.c
+++ b/hal/audio_extn/cirrus_playback.c
@@ -19,7 +19,7 @@
 
 #include <errno.h>
 #include <math.h>
-#include <cutils/log.h>
+#include <log/log.h>
 #include <fcntl.h>
 #include "../audio_hw.h"
 #include "platform.h"
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <dlfcn.h>
 #include <math.h>
+#include <pthread.h>
 #include <time.h>
 #include <unistd.h>
 #include <cutils/properties.h>
@@ -38,12 +39,21 @@
 
 struct cirrus_playback_session {
     void *adev_handle;
-    pthread_mutex_t mutex_fb_prot;
-    pthread_mutex_t mutex_pcm_stream;
-    pthread_t pcm_stream_thread;
+    pthread_mutex_t fb_prot_mutex;
+    pthread_t calibration_thread;
+#ifdef ENABLE_CIRRUS_DETECTION
+    pthread_t failure_detect_thread;
+#endif
     struct pcm *pcm_rx;
     struct pcm *pcm_tx;
-    bool spkr_prot_enable;
+    volatile int32_t state;
+};
+
+enum cirrus_playback_state {
+    INIT = 0,
+    CALIBRATING = 1,
+    IDLE = 2,
+    PLAYBACK = 3
 };
 
 struct crus_sp_ioctl_header {
@@ -62,7 +72,6 @@
     int32_t status_r;
     int32_t checksum_r;
     int32_t z_r;
-    int32_t atemp;
 };
 
 /* Payload struct for setting the RX and TX use cases */
@@ -74,13 +83,17 @@
     int32_t status_r;
     int32_t checksum_r;
     int32_t z_r;
-    int32_t atemp;
 };
 
 #define CRUS_SP_FILE "/dev/msm_cirrus_playback"
 #define CRUS_CAL_FILE "/persist/audio/audio.cal"
-#define CRUS_SP_USECASE_MIXER "Cirrus SP Usecase Config"
-#define CRUS_SP_EXT_CONFIG_MIXER "Cirrus SP EXT Config"
+#define CRUS_TX_CONF_FILE "vendor/firmware/crus_sp_config_%s_tx.bin"
+#define CRUS_RX_CONF_FILE "vendor/firmware/crus_sp_config_%s_rx.bin"
+#define CONFIG_FILE_SIZE 128
+
+#define CRUS_SP_USECASE_MIXER   "Cirrus SP Usecase"
+#define CRUS_SP_LOAD_CONF_MIXER "Cirrus SP Load Config"
+#define CRUS_SP_FAIL_DET_MIXER  "Cirrus SP Failure Detection"
 
 #define CIRRUS_SP 0x10027053
 
@@ -103,6 +116,12 @@
 
 #define CRUS_AFE_PARAM_ID_ENABLE 0x00010203
 
+#define FAIL_DETECT_INIT_WAIT_US 500000
+#define FAIL_DETECT_LOOP_WAIT_US 300000
+
+#define CRUS_DEFAULT_CAL_L 0x2A11
+#define CRUS_DEFAULT_CAL_R 0x29CB
+
 #define CRUS_SP_IOCTL_MAGIC 'a'
 
 #define CRUS_SP_IOCTL_GET _IOWR(CRUS_SP_IOCTL_MAGIC, 219, void *)
@@ -110,7 +129,7 @@
 #define CRUS_SP_IOCTL_GET_CALIB _IOWR(CRUS_SP_IOCTL_MAGIC, 221, void *)
 #define CRUS_SP_IOCTL_SET_CALIB _IOWR(CRUS_SP_IOCTL_MAGIC, 222, void *)
 
-#define CRUS_SP_DEFAULT_AMBIENT_TEMP 23
+
 
 static struct pcm_config pcm_config_cirrus_tx = {
     .channels = 2,
@@ -124,11 +143,11 @@
 };
 
 static struct pcm_config pcm_config_cirrus_rx = {
-    .channels = 2,
+    .channels = 8,
     .rate = 48000,
     .period_size = 320,
     .period_count = 4,
-    .format = PCM_FORMAT_S16_LE,
+    .format = PCM_FORMAT_S32_LE,
     .start_threshold = 0,
     .stop_threshold = INT_MAX,
     .avail_min = 0,
@@ -136,21 +155,65 @@
 
 static struct cirrus_playback_session handle;
 
-static void *audio_extn_cirrus_run_calibration() {
+#ifdef CIRRUS_FACTORY_CALIBRATION
+static void *audio_extn_cirrus_calibration_thread();
+#else
+static void *audio_extn_cirrus_config_thread();
+#endif
+
+#ifdef ENABLE_CIRRUS_DETECTION
+static void *audio_extn_cirrus_failure_detect_thread();
+#endif
+
+void audio_extn_spkr_prot_init(void *adev) {
+    ALOGI("%s: Initialize Cirrus Logic Playback module", __func__);
+
+    memset(&handle, 0, sizeof(handle));
+    if (!adev) {
+        ALOGE("%s: Invalid params", __func__);
+        return;
+    }
+
+    handle.adev_handle = adev;
+    handle.state = INIT;
+
+    pthread_mutex_init(&handle.fb_prot_mutex, NULL);
+
+#ifdef CIRRUS_FACTORY_CALIBRATION
+    (void)pthread_create(&handle.calibration_thread,
+                (const pthread_attr_t *) NULL,
+                audio_extn_cirrus_calibration_thread, &handle);
+#else
+    (void)pthread_create(&handle.calibration_thread,
+                (const pthread_attr_t *) NULL,
+                audio_extn_cirrus_config_thread, &handle);
+#endif
+}
+
+void audio_extn_spkr_prot_deinit(void *adev __unused) {
+    ALOGV("%s: Entry", __func__);
+
+#ifdef ENABLE_CIRRUS_DETECTION
+    pthread_join(handle.failure_detect_thread, NULL);
+#endif
+    pthread_join(handle.calibration_thread, NULL);
+    pthread_mutex_destroy(&handle.fb_prot_mutex);
+
+    ALOGV("%s: Exit", __func__);
+}
+
+#ifdef CIRRUS_FACTORY_CALIBRATION
+static int audio_extn_cirrus_run_calibration() {
     struct audio_device *adev = handle.adev_handle;
     struct crus_sp_ioctl_header header;
     struct cirrus_cal_result_t result;
-    struct mixer_ctl *ctl;
-    FILE *cal_file;
-    int ret = 0, dev_file;
+    struct mixer_ctl *ctl = NULL;
+    FILE *cal_file = NULL;
+    int ret = 0, dev_file = -1;
     char *buffer = NULL;
     uint32_t option = 1;
-    struct timespec timeout;
 
-    ALOGI("%s: Calibration thread", __func__);
-
-    timeout.tv_sec = 10;
-    timeout.tv_nsec = 0;
+    ALOGI("%s: Running speaker calibration", __func__);
 
     dev_file = open(CRUS_SP_FILE, O_RDWR | O_NONBLOCK);
     if (dev_file < 0) {
@@ -162,17 +225,17 @@
 
     buffer = calloc(1, CRUS_PARAM_TEMP_MAX_LENGTH);
     if (!buffer) {
-        ret = -EINVAL;
+        ALOGE("%s: allocate memory failed", __func__);
+        ret = -ENOMEM;
         goto exit;
     }
 
     cal_file = fopen(CRUS_CAL_FILE, "r");
     if (cal_file) {
-        size_t bytes;
-        bytes = fread(&result, 1, sizeof(result), cal_file);
-        if (bytes < sizeof(result)) {
-            ALOGE("%s: Cirrus SP calibration file cannot be read (%d)",
-                  __func__, ret);
+        ret = fread(&result, sizeof(result), 1, cal_file);
+        if (ret != 1) {
+            ALOGE("%s: Cirrus SP calibration file cannot be read , read size: %lu file error: %d",
+                  __func__, (unsigned long)ret * sizeof(result), ferror(cal_file));
             ret = -EINVAL;
             fclose(cal_file);
             goto exit;
@@ -227,9 +290,43 @@
             goto exit;
         }
 
-        result.atemp = CRUS_SP_DEFAULT_AMBIENT_TEMP;
+        if (result.status_l != 1) {
+            ALOGE("%s: Left calibration failure. Please check speakers",
+                    __func__);
+            ret = -EINVAL;
+        }
 
-        // TODO: Save calibrated data to file
+        if (result.status_r != 1) {
+            ALOGE("%s: Right calibration failure. Please check speakers",
+                    __func__);
+            ret = -EINVAL;
+        }
+
+        if (ret < 0)
+            goto exit;
+
+        cal_file = fopen(CRUS_CAL_FILE, "wb");
+        if (cal_file == NULL) {
+            ALOGE("%s: Cannot create Cirrus SP calibration file (%s)",
+                  __func__, strerror(errno));
+            ret = -EINVAL;
+            goto exit;
+        }
+
+        ret = fwrite(&result, sizeof(result), 1, cal_file);
+
+        if (ret != 1) {
+            ALOGE("%s: Unable to save Cirrus SP calibration data, write size %lu, file error %d",
+                  __func__, (unsigned long)ret * sizeof(result), ferror(cal_file));
+            fclose(cal_file);
+            ret = -EINVAL;
+            goto exit;
+        }
+
+        fclose(cal_file);
+
+        ALOGI("%s: Cirrus calibration file successfully written",
+              __func__);
     }
 
     header.size = sizeof(header);
@@ -242,28 +339,31 @@
 
     if (ret < 0) {
         ALOGE("%s: Cirrus SP calibration IOCTL failure (%d)", __func__, ret);
-        close(dev_file);
         ret = -EINVAL;
         goto exit;
     }
 
     ctl = mixer_get_ctl_by_name(adev->mixer,
-                                CRUS_SP_USECASE_MIXER);
+                    CRUS_SP_USECASE_MIXER);
     if (!ctl) {
         ALOGE("%s: Could not get ctl for mixer cmd - %s",
-              __func__, CRUS_SP_USECASE_MIXER);
+             __func__, CRUS_SP_USECASE_MIXER);
         ret = -EINVAL;
         goto exit;
     }
 
-    mixer_ctl_set_value(ctl, 0, 0); // Set RX external firmware config
+    ret = mixer_ctl_set_value(ctl, 0, 0); // Set RX external firmware config
+    if (ret < 0) {
+        ALOGE("%s: set default usecase failed", __func__);
+        goto exit;
+    }
 
     sleep(1);
 
     header.size = sizeof(header);
     header.module_id = CRUS_MODULE_ID_RX;
     header.param_id = CRUS_PARAM_RX_GET_TEMP;
-    header.data_length = sizeof(buffer);
+    header.data_length = CRUS_PARAM_TEMP_MAX_LENGTH;
     header.data = buffer;
 
     ret = ioctl(dev_file, CRUS_SP_IOCTL_GET, &header);
@@ -276,24 +376,92 @@
     ALOGI("%s: Cirrus SP successfully calibrated", __func__);
 
 exit:
-    close(dev_file);
+    if (dev_file >= 0)
+        close(dev_file);
     free(buffer);
     ALOGV("%s: Exit", __func__);
 
-    return NULL;
+    return ret;
 }
 
+static int audio_extn_cirrus_load_usecase_configs(void) {
+    struct audio_device *adev = handle.adev_handle;
+    struct mixer_ctl *ctl_uc = NULL, *ctl_config = NULL;
+    char *filename = NULL;
+    int ret = 0, default_uc = 0;
+    struct snd_card_split *snd_split_handle = NULL;
+    snd_split_handle = audio_extn_get_snd_card_split();
 
-static void *audio_extn_cirrus_pcm_stream_thread() {
+    ALOGI("%s: Loading usecase tuning configs", __func__);
+
+    ctl_uc = mixer_get_ctl_by_name(adev->mixer, CRUS_SP_USECASE_MIXER);
+    ctl_config = mixer_get_ctl_by_name(adev->mixer,
+                    CRUS_SP_LOAD_CONF_MIXER);
+    if (!ctl_uc || !ctl_config) {
+        ALOGE("%s: Could not get ctl for mixer commands", __func__);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    filename = calloc(1 , CONFIG_FILE_SIZE);
+    if (!filename) {
+        ALOGE("%s: allocate memory failed", __func__);
+        ret = -ENOMEM;
+        goto exit;
+    }
+
+    default_uc = mixer_ctl_get_value(ctl_uc, 0);
+
+    ret = mixer_ctl_set_value(ctl_uc, 0, default_uc);
+    if (ret < 0) {
+        ALOGE("%s set uscase %d failed", __func__, default_uc);
+        goto exit;
+    }
+
+    /* Load TX Tuning Config (if available) */
+    snprintf(filename, CONFIG_FILE_SIZE, CRUS_TX_CONF_FILE, snd_split_handle->form_factor);
+    if (access(filename, R_OK) == 0) {
+        ret = mixer_ctl_set_value(ctl_config, 0, 2);
+        if (ret < 0) {
+            ALOGE("%s set tx config failed", __func__);
+            goto exit;
+        }
+    } else {
+        ALOGE("%s: Tuning file not found (%s)", __func__,
+              filename);
+        ret = -EINVAL;
+        goto exit;
+    }
+    /* Load RX Tuning Config (if available) */
+    snprintf(filename, CONFIG_FILE_SIZE, CRUS_RX_CONF_FILE, snd_split_handle->form_factor);
+    if (access(filename, R_OK) == 0) {
+        ret = mixer_ctl_set_value(ctl_config, 0, 1);
+        if (ret < 0) {
+            ALOGE("%s set rx config failed", __func__);
+            goto exit;
+        }
+    } else {
+        ALOGE("%s: Tuning file not found (%s)", __func__,
+              filename);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    ALOGI("%s: Cirrus SP loaded available usecase configs", __func__);
+exit:
+    free(filename);
+    ALOGI("%s: Exit", __func__);
+
+    return ret;
+}
+
+static void *audio_extn_cirrus_calibration_thread() {
     struct audio_device *adev = handle.adev_handle;
     struct audio_usecase *uc_info_rx = NULL;
     int ret = 0;
-    int32_t pcm_dev_rx_id = 0;
-    uint32_t rx_use_case = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
+    int32_t pcm_dev_rx_id, prev_state;
     uint32_t retries = 5;
 
-    pthread_mutex_lock(&handle.mutex_pcm_stream);
-
     ALOGI("%s: PCM Stream thread", __func__);
 
     while (!adev->platform && retries) {
@@ -302,13 +470,17 @@
         retries--;
     }
 
-    uc_info_rx = (struct audio_usecase *)calloc(1, sizeof(*uc_info_rx));
+    prev_state = handle.state;
+    handle.state = CALIBRATING;
+
+    uc_info_rx = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
     if (!uc_info_rx) {
-        ret = -EINVAL;
+        ALOGE("%s: rx usecase can not be found", __func__);
         goto exit;
     }
+    pthread_mutex_lock(&adev->lock);
 
-    uc_info_rx->id = rx_use_case;
+    uc_info_rx->id = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
     uc_info_rx->type = PCM_PLAYBACK;
     uc_info_rx->in_snd_device = SND_DEVICE_NONE;
     uc_info_rx->stream.out = adev->primary_output;
@@ -317,77 +489,314 @@
 
     enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER);
     enable_audio_route(adev, uc_info_rx);
-    handle.pcm_rx = pcm_open(adev->snd_card, pcm_dev_rx_id,
-                             PCM_OUT, &pcm_config_cirrus_rx);
+    pcm_dev_rx_id = platform_get_pcm_device_id(uc_info_rx->id, PCM_PLAYBACK);
 
-    if (!handle.pcm_rx || !pcm_is_ready(handle.pcm_rx)) {
+    if (pcm_dev_rx_id < 0) {
+        ALOGE("%s: Invalid pcm device for usecase (%d)",
+              __func__, uc_info_rx->id);
+        pthread_mutex_unlock(&adev->lock);
+        goto exit;
+    }
+
+    handle.pcm_rx = pcm_open(adev->snd_card, pcm_dev_rx_id,
+                PCM_OUT, &pcm_config_cirrus_rx);
+
+    if (handle.pcm_rx && !pcm_is_ready(handle.pcm_rx)) {
         ALOGE("%s: PCM device not ready: %s", __func__,
-              pcm_get_error(handle.pcm_rx ? handle.pcm_rx : 0));
-        ret = -EINVAL;
+              pcm_get_error(handle.pcm_rx));
+        pthread_mutex_unlock(&adev->lock);
         goto close_stream;
     }
 
     if (pcm_start(handle.pcm_rx) < 0) {
         ALOGE("%s: pcm start for RX failed; error = %s", __func__,
               pcm_get_error(handle.pcm_rx));
-        ret = -EINVAL;
+        pthread_mutex_unlock(&adev->lock);
         goto close_stream;
     }
+    pthread_mutex_unlock(&adev->lock);
+    ALOGI("%s: PCM thread streaming", __func__);
 
-    ALOGV("%s: PCM thread streaming", __func__);
+    ret = audio_extn_cirrus_run_calibration();
+    ALOGE_IF(ret < 0, "%s: Calibration procedure failed (%d)", __func__, ret);
 
-    audio_extn_cirrus_run_calibration();
+    ret = audio_extn_cirrus_load_usecase_configs();
+    ALOGE_IF(ret < 0, "%s: Set tuning configs failed (%d)", __func__, ret);
 
 close_stream:
+    pthread_mutex_lock(&adev->lock);
     if (handle.pcm_rx) {
-        ALOGV("%s: pcm_rx_close", __func__);
+        ALOGI("%s: pcm_rx_close", __func__);
         pcm_close(handle.pcm_rx);
         handle.pcm_rx = NULL;
     }
-
     disable_audio_route(adev, uc_info_rx);
     disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER);
     list_remove(&uc_info_rx->list);
     free(uc_info_rx);
-
+    pthread_mutex_unlock(&adev->lock);
 exit:
-    pthread_mutex_unlock(&handle.mutex_pcm_stream);
+    handle.state = (prev_state == PLAYBACK) ? PLAYBACK : IDLE;
+
+#ifdef ENABLE_CIRRUS_DETECTION
+    if (handle.state == PLAYBACK)
+        (void)pthread_create(&handle.failure_detect_thread,
+                    (const pthread_attr_t *) NULL,
+                    audio_extn_cirrus_failure_detect_thread,
+                    &handle);
+#endif
+
     ALOGV("%s: Exit", __func__);
 
     pthread_exit(0);
     return NULL;
 }
 
-void audio_extn_spkr_prot_init(void *adev) {
-    ALOGI("%s: Initialize Cirrus Logic Playback module", __func__);
+#else
+static void *audio_extn_cirrus_config_thread(void) {
+    struct audio_device *adev = handle.adev_handle;
+    struct crus_sp_ioctl_header header;
+    struct cirrus_cal_result_t result;
+    struct mixer_ctl *ctl_config = NULL;
+    FILE *cal_file = NULL;
+    int ret = 0, dev_file = -1;
 
-    struct snd_card_split *snd_split_handle = NULL;
+    ALOGI("%s: ++", __func__);
 
-    if (!adev) {
-        ALOGE("%s: Invalid params", __func__);
-        return;
+    memset(&result, 0, sizeof(result));
+
+    dev_file = open(CRUS_SP_FILE, O_RDWR | O_NONBLOCK);
+    if (dev_file < 0) {
+        ALOGE("%s: Failed to open Cirrus Playback IOCTL (%d)",
+              __func__, dev_file);
+        ret = -EINVAL;
+        goto exit;
     }
 
-    memset(&handle, 0, sizeof(handle));
+    cal_file = fopen(CRUS_CAL_FILE, "r");
+    if (cal_file) {
+        ret = fread(&result, sizeof(result), 1, cal_file);
 
-    snd_split_handle = audio_extn_get_snd_card_split();
-
-    /* FIXME: REMOVE THIS AFTER B1C1 P1.0 SUPPORT */
-    if (!strcmp(snd_split_handle->form_factor, "tdm")) {
-        handle.spkr_prot_enable = true;
-    } else {
-        handle.spkr_prot_enable = false;
+        if (ret != 1) {
+            ALOGE("%s: Cirrus SP calibration file cannot be read , read size: %lu file error: %d",
+                 __func__, (unsigned long)ret * sizeof(result), ferror(cal_file));
+            ret = -EINVAL;
+            goto exit;
+        }
     }
 
-    handle.adev_handle = adev;
+    header.size = sizeof(header);
+    header.module_id = CRUS_MODULE_ID_TX;
+    header.param_id = 0;
+    header.data_length = sizeof(result);
+    header.data = &result;
 
-    pthread_mutex_init(&handle.mutex_fb_prot, NULL);
-    pthread_mutex_init(&handle.mutex_pcm_stream, NULL);
+    ret = ioctl(dev_file, CRUS_SP_IOCTL_SET_CALIB, &header);
 
-    (void)pthread_create(&handle.pcm_stream_thread,
-                         (const pthread_attr_t *) NULL,
-                         audio_extn_cirrus_pcm_stream_thread, &handle);
+    if (ret < 0) {
+        ALOGE("%s: Cirrus SP calibration IOCTL failure", __func__);
+        goto exit;
+    }
+
+    ctl_config = mixer_get_ctl_by_name(adev->mixer,
+                       CRUS_SP_LOAD_CONF_MIXER);
+    if (!ctl_config) {
+        ALOGE("%s: Could not get ctl for mixer commands", __func__);
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    ret = mixer_ctl_set_value(ctl_config, 0, 2);
+    if (ret < 0) {
+        ALOGE("%s load tx config failed", __func__);
+        goto exit;
+    }
+
+    ret = mixer_ctl_set_value(ctl_config, 0, 1);
+    if (ret < 0) {
+        ALOGE("%s load rx config failed", __func__);
+        goto exit;
+    }
+
+    ret = mixer_ctl_set_value(ctl_config, 0, 0);
+    if (ret < 0) {
+        ALOGE("%s set idle state failed", __func__);
+        goto exit;
+    }
+
+exit:
+    if (dev_file >= 0)
+        close(dev_file);
+    if (cal_file)
+        fclose(cal_file);
+
+    ALOGI("%s: ret: %d --", __func__, ret);
+    return NULL;
 }
+#endif
+
+#ifdef ENABLE_CIRRUS_DETECTION
+void *audio_extn_cirrus_failure_detect_thread() {
+    struct audio_device *adev = handle.adev_handle;
+    struct crus_sp_ioctl_header header;
+    struct mixer_ctl *ctl = NULL;
+    const int32_t r_scale_factor = 100000000;
+    const int32_t t_scale_factor = 100000;
+    const int32_t r_err_range = 70000000;
+    const int32_t t_err_range = 210000;
+    const int32_t amp_factor = 71498;
+    const int32_t material = 250;
+    int32_t *buffer = NULL;
+    int ret = 0, dev_file = -1, out_cal0 = 0, out_cal1 = 0;
+    int rL = 0, rR = 0, zL = 0, zR = 0, tL = 0, tR = 0;
+    int rdL = 0, rdR = 0, tdL = 0, tdR = 0, ambL = 0, ambR = 0;
+    bool left_cal_done = false, right_cal_done = false;
+    bool det_en = false;
+
+    ALOGI("%s: Entry", __func__);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, CRUS_SP_FAIL_DET_MIXER);
+    det_en = mixer_ctl_get_value(ctl, 0);
+
+    if (!det_en)
+        goto exit;
+
+    dev_file = open(CRUS_SP_FILE, O_RDWR | O_NONBLOCK);
+    if (dev_file < 0) {
+        ALOGE("%s: Failed to open Cirrus Playback IOCTL (%d)",
+                __func__, dev_file);
+        goto exit;
+    }
+
+    buffer = calloc(1, CRUS_PARAM_TEMP_MAX_LENGTH);
+    if (!buffer) {
+        ALOGE("%s: allocate memory failed", __func__);
+        goto exit;
+    }
+
+    header.size = sizeof(header);
+    header.module_id = CRUS_MODULE_ID_RX;
+    header.param_id = CRUS_PARAM_RX_GET_TEMP;
+    header.data_length = CRUS_PARAM_TEMP_MAX_LENGTH;
+    header.data = buffer;
+
+    usleep(FAIL_DETECT_INIT_WAIT_US);
+
+    pthread_mutex_lock(&handle.fb_prot_mutex);
+    ret = ioctl(dev_file, CRUS_SP_IOCTL_GET, &header);
+    pthread_mutex_unlock(&handle.fb_prot_mutex);
+    if (ret < 0) {
+        ALOGE("%s: Cirrus SP IOCTL failure (%d)",
+               __func__, ret);
+        goto exit;
+    }
+
+    zL = buffer[2] * amp_factor;
+    zR = buffer[4] * amp_factor;
+
+    ambL = buffer[10];
+    ambR = buffer[6];
+
+    out_cal0 = buffer[12];
+    out_cal1 = buffer[13];
+
+    left_cal_done = (out_cal0 == 2) && (out_cal1 == 2) &&
+                    (buffer[2] != CRUS_DEFAULT_CAL_L);
+
+    out_cal0 = buffer[14];
+    out_cal1 = buffer[15];
+
+    right_cal_done = (out_cal0 == 2) && (out_cal1 == 2) &&
+                     (buffer[4] != CRUS_DEFAULT_CAL_R);
+
+    if (left_cal_done) {
+        ALOGI("%s: L Speaker Impedance: %d.%08d ohms", __func__,
+              zL / r_scale_factor, abs(zL) % r_scale_factor);
+        ALOGI("%s: L Calibration Temperature: %d C", __func__, ambL);
+    } else
+        ALOGE("%s: Left speaker uncalibrated", __func__);
+
+    if (right_cal_done) {
+        ALOGI("%s: R Speaker Impedance: %d.%08d ohms", __func__,
+               zR / r_scale_factor, abs(zR) % r_scale_factor);
+        ALOGI("%s: R Calibration Temperature: %d C", __func__, ambR);
+    } else
+        ALOGE("%s: Right speaker uncalibrated", __func__);
+
+    if (!left_cal_done && !right_cal_done)
+        goto exit;
+
+    ALOGI("%s: Monitoring speaker impedance & temperature...", __func__);
+
+    while ((handle.state == PLAYBACK) && det_en) {
+        pthread_mutex_lock(&handle.fb_prot_mutex);
+        ret = ioctl(dev_file, CRUS_SP_IOCTL_GET, &header);
+        pthread_mutex_unlock(&handle.fb_prot_mutex);
+        if (ret < 0) {
+            ALOGE("%s: Cirrus SP IOCTL failure (%d)",
+                  __func__, ret);
+            goto loop;
+        }
+
+        rL = buffer[3];
+        rR = buffer[1];
+
+        zL = buffer[2];
+        zR = buffer[4];
+
+        if ((zL == 0) || (zR == 0))
+            goto loop;
+
+        tdL = (material * t_scale_factor * (rL-zL) / zL);
+        tdR = (material * t_scale_factor * (rR-zR) / zR);
+
+        rL *= amp_factor;
+        rR *= amp_factor;
+
+        zL *= amp_factor;
+        zR *= amp_factor;
+
+        tL = tdL + (ambL * t_scale_factor);
+        tR = tdR + (ambR * t_scale_factor);
+
+        rdL = abs(zL - rL);
+        rdR = abs(zR - rR);
+
+        if (left_cal_done && (rL != 0) && (rdL > r_err_range))
+            ALOGI("%s: Left speaker impedance out of range (%d.%08d ohms)",
+                  __func__, rL / r_scale_factor,
+                  abs(rL % r_scale_factor));
+
+        if (right_cal_done && (rR != 0) && (rdR > r_err_range))
+            ALOGI("%s: Right speaker impedance out of range (%d.%08d ohms)",
+                  __func__, rR / r_scale_factor,
+                  abs(rR % r_scale_factor));
+
+        if (left_cal_done && (rL != 0) && (tdL > t_err_range))
+            ALOGI("%s: Left speaker temperature out of range (%d.%05d C)",
+                  __func__, tL / t_scale_factor,
+                  abs(tL % t_scale_factor));
+
+        if (right_cal_done && (rR != 0) && (tdR > t_err_range))
+            ALOGI("%s: Right speaker temperature out of range (%d.%05d C)",
+                  __func__, tR / t_scale_factor,
+                  abs(tR % t_scale_factor));
+
+loop:
+        det_en = mixer_ctl_get_value(ctl, 0);
+        usleep(FAIL_DETECT_LOOP_WAIT_US);
+    }
+
+exit:
+    if (dev_file >= 0)
+        close(dev_file);
+    free(buffer);
+    ALOGI("%s: Exit ", __func__);
+
+    pthread_exit(0);
+    return NULL;
+}
+#endif
 
 int audio_extn_spkr_prot_start_processing(snd_device_t snd_device) {
     struct audio_usecase *uc_info_tx;
@@ -403,13 +812,14 @@
 
     uc_info_tx = (struct audio_usecase *)calloc(1, sizeof(*uc_info_tx));
     if (!uc_info_tx) {
+        ALOGE("%s: allocate memory failed", __func__);
         return -ENOMEM;
     }
 
     audio_route_apply_and_update_path(adev->audio_route,
                                       platform_get_snd_device_name(snd_device));
 
-    pthread_mutex_lock(&handle.mutex_fb_prot);
+    pthread_mutex_lock(&handle.fb_prot_mutex);
     uc_info_tx->id = USECASE_AUDIO_SPKR_CALIB_TX;
     uc_info_tx->type = PCM_CAPTURE;
     uc_info_tx->in_snd_device = SND_DEVICE_IN_CAPTURE_VI_FEEDBACK;
@@ -434,26 +844,31 @@
                              pcm_dev_tx_id,
                              PCM_IN, &pcm_config_cirrus_tx);
 
-    if (!handle.pcm_tx || !pcm_is_ready(handle.pcm_tx)) {
-        ALOGD("%s: PCM device not ready: %s", __func__,
-              pcm_get_error(handle.pcm_tx ? handle.pcm_tx : 0));
+    if (handle.pcm_tx && !pcm_is_ready(handle.pcm_tx)) {
+        ALOGE("%s: PCM device not ready: %s", __func__, pcm_get_error(handle.pcm_tx));
         ret = -EIO;
         goto exit;
     }
 
     if (pcm_start(handle.pcm_tx) < 0) {
-        ALOGI("%s: retrying pcm_start...", __func__);
-	usleep(500 * 1000);
-        if (pcm_start(handle.pcm_tx) < 0) {
-            ALOGI("%s: pcm start for TX failed; error = %s", __func__,
-                  pcm_get_error(handle.pcm_tx));
-            ret = -EINVAL;
-        }
+        ALOGE("%s: pcm start for TX failed; error = %s", __func__,
+              pcm_get_error(handle.pcm_tx));
+        ret = -EINVAL;
+        goto exit;
     }
 
+#ifdef ENABLE_CIRRUS_DETECTION
+    if (handle.state == IDLE)
+        (void)pthread_create(&handle.failure_detect_thread,
+                    (const pthread_attr_t *) NULL,
+                    audio_extn_cirrus_failure_detect_thread,
+                    &handle);
+#endif
+
+    handle.state = PLAYBACK;
 exit:
     if (ret) {
-        ALOGI("%s: Disable and bail out", __func__);
+        handle.state = IDLE;
         if (handle.pcm_tx) {
             ALOGI("%s: pcm_tx_close", __func__);
             pcm_close(handle.pcm_tx);
@@ -466,7 +881,7 @@
         free(uc_info_tx);
     }
 
-    pthread_mutex_unlock(&handle.mutex_fb_prot);
+    pthread_mutex_unlock(&handle.fb_prot_mutex);
     ALOGV("%s: Exit", __func__);
     return ret;
 }
@@ -477,8 +892,9 @@
 
     ALOGV("%s: Entry", __func__);
 
-    pthread_mutex_lock(&handle.mutex_fb_prot);
+    pthread_mutex_lock(&handle.fb_prot_mutex);
 
+    handle.state = IDLE;
     uc_info_tx = get_usecase_from_list(adev, USECASE_AUDIO_SPKR_CALIB_TX);
 
     if (uc_info_tx) {
@@ -497,36 +913,22 @@
                                platform_get_snd_device_name(snd_device));
     }
 
-    pthread_mutex_unlock(&handle.mutex_fb_prot);
+    pthread_mutex_unlock(&handle.fb_prot_mutex);
 
     ALOGV("%s: Exit", __func__);
 }
 
 bool audio_extn_spkr_prot_is_enabled() {
-    return handle.spkr_prot_enable;
-}
-
-int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device) {
-    int acdb_id;
-
-    switch (snd_device) {
-    case SND_DEVICE_OUT_SPEAKER:
-        acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED);
-        break;
-    case SND_DEVICE_OUT_VOICE_SPEAKER:
-        acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED);
-        break;
-    default:
-        acdb_id = -EINVAL;
-        break;
-    }
-    return acdb_id;
+    return true;
 }
 
 int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device) {
     switch(snd_device) {
     case SND_DEVICE_OUT_SPEAKER:
+    case SND_DEVICE_OUT_SPEAKER_REVERSE:
         return SND_DEVICE_OUT_SPEAKER_PROTECTED;
+    case SND_DEVICE_OUT_SPEAKER_SAFE:
+        return SND_DEVICE_OUT_SPEAKER_SAFE;
     case SND_DEVICE_OUT_VOICE_SPEAKER:
         return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED;
     default:
diff --git a/hal/audio_extn/maxxaudio.c b/hal/audio_extn/maxxaudio.c
index 73bd641..fc65332 100644
--- a/hal/audio_extn/maxxaudio.c
+++ b/hal/audio_extn/maxxaudio.c
@@ -17,40 +17,41 @@
 #define LOG_TAG "audio_hw_waves"
 /*#define LOG_NDEBUG 0*/
 
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <cutils/str_parms.h>
-#include <log/log.h>
 #include <audio_hw.h>
-#include <system/audio.h>
-#include <platform_api.h>
-#include <string.h>
+#include <cutils/str_parms.h>
+#include <dlfcn.h>
+#include <log/log.h>
 #include <math.h>
+#include <platform_api.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <system/audio.h>
+#include <unistd.h>
+
 #include "audio_extn.h"
 #include "maxxaudio.h"
 
-#define LIB_MA_PARAM "libmaqdspparams.so"
+#define LIB_MA_PARAM "libmaxxaudioqdsp.so"
 #define LIB_MA_PATH "vendor/lib/"
-#define PRESET_PATH "/vendor/etc/default.mps"
+#define PRESET_PATH "/vendor/etc"
+#define MPS_BASE_STRING "default"
 #define USER_PRESET_PATH ""
-#define CONFIG_PATH "/vendor/etc/maxx_conf.ini"
+#define CONFIG_BASE_STRING "maxx_conf"
 #define CAL_PRESIST_STR "cal_persist"
 #define CAL_SAMPLERATE_STR "cal_samplerate"
 
-#define MA_QDSP_PARAM_INIT "maxxaudio_qdsp_parameters_initialize"
-#define MA_QDSP_PARAM_DEINIT "maxxaudio_qdsp_parameters_uninitialize"
+#define MA_QDSP_PARAM_INIT "maxxaudio_qdsp_initialize"
+#define MA_QDSP_PARAM_DEINIT "maxxaudio_qdsp_uninitialize"
 #define MA_QDSP_SET_LR_SWAP "maxxaudio_qdsp_set_lr_swap"
 #define MA_QDSP_SET_MODE "maxxaudio_qdsp_set_sound_mode"
 #define MA_QDSP_SET_VOL "maxxaudio_qdsp_set_volume"
 #define MA_QDSP_SET_VOLT "maxxaudio_qdsp_set_volume_table"
 
 #define SUPPORT_DEV "Blackbird"
-#define SUPPORTED_USB  0x01
+#define SUPPORTED_USB 0x01
 
 struct ma_audio_cal_settings {
-    void *platform;
     int app_type;
     audio_devices_t device;
 };
@@ -78,34 +79,30 @@
 } ma_cmd_t;
 
 typedef void *ma_audio_cal_handle_t;
-typedef int (*set_audio_cal_t)(const struct ma_audio_cal_settings *, const char *);
+typedef int (*set_audio_cal_t)(const char *);
 
-typedef bool (*ma_param_init_t)(
-                ma_audio_cal_handle_t *,
-                void *, const char *, const char *,
-                const char *, set_audio_cal_t);
+typedef bool (*ma_param_init_t)(ma_audio_cal_handle_t *, const char *,
+                                const char *, const char *, set_audio_cal_t);
 
-typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t);
+typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t *);
 
-typedef bool (*ma_set_lr_swap_t)(
-                ma_audio_cal_handle_t,
-                const struct ma_audio_cal_settings *, bool);
+typedef bool (*ma_set_lr_swap_t)(ma_audio_cal_handle_t,
+                                 const struct ma_audio_cal_settings *, bool);
 
-typedef bool (*ma_set_sound_mode_t)(
-                ma_audio_cal_handle_t,
-                const struct ma_audio_cal_settings *, unsigned int);
+typedef bool (*ma_set_sound_mode_t)(ma_audio_cal_handle_t,
+                                    const struct ma_audio_cal_settings *,
+                                    unsigned int);
 
-typedef bool (*ma_set_volume_t)(
-                ma_audio_cal_handle_t,
-                const struct ma_audio_cal_settings *, double);
+typedef bool (*ma_set_volume_t)(ma_audio_cal_handle_t,
+                                const struct ma_audio_cal_settings *, double);
 
-typedef bool (*ma_set_volume_table_t)(
-                ma_audio_cal_handle_t,
-                const struct ma_audio_cal_settings *,
-                size_t, struct ma_state *);
+typedef bool (*ma_set_volume_table_t)(ma_audio_cal_handle_t,
+                                      const struct ma_audio_cal_settings *,
+                                      size_t, struct ma_state *);
 
 struct ma_platform_data {
     void *waves_handle;
+    void *platform;
     pthread_mutex_t lock;
     ma_param_init_t          ma_param_init;
     ma_param_deinit_t        ma_param_deinit;
@@ -120,49 +117,42 @@
 static struct ma_state ma_cur_state_table[STREAM_MAX_TYPES];
 static struct ma_platform_data *my_data = NULL;
 
-static int set_audio_cal(
-        const struct ma_audio_cal_settings *audio_cal_settings,
-        const char *audio_cal)
-
+static int set_audio_cal(const char *audio_cal)
 {
     ALOGV("set_audio_cal: %s", audio_cal);
 
-    return platform_set_parameters(audio_cal_settings->platform,
+    return platform_set_parameters(my_data->platform,
                                    str_parms_create_str(audio_cal));
 }
 
 static bool ma_set_lr_swap_l(
-        const struct ma_audio_cal_settings *audio_cal_settings,
-        bool swap)
+    const struct ma_audio_cal_settings *audio_cal_settings, bool swap)
 {
-    return my_data->ma_set_lr_swap(g_ma_audio_cal_handle, audio_cal_settings, swap);
+    return my_data->ma_set_lr_swap(g_ma_audio_cal_handle,
+                                   audio_cal_settings, swap);
 }
 
 static bool ma_set_sound_mode_l(
-        const struct ma_audio_cal_settings *audio_cal_settings,
-        int sound_mode)
+    const struct ma_audio_cal_settings *audio_cal_settings, int sound_mode)
 {
     return my_data->ma_set_sound_mode(g_ma_audio_cal_handle,
-                                        audio_cal_settings, sound_mode);
+                                      audio_cal_settings, sound_mode);
 }
 
 static bool ma_set_volume_l(
-        const struct ma_audio_cal_settings *audio_cal_settings,
-        double volume)
+    const struct ma_audio_cal_settings *audio_cal_settings, double volume)
 {
-    return my_data->ma_set_volume(g_ma_audio_cal_handle, audio_cal_settings, volume);
+    return my_data->ma_set_volume(g_ma_audio_cal_handle, audio_cal_settings,
+                                  volume);
 }
 
 static bool ma_set_volume_table_l(
-        const struct ma_audio_cal_settings *audio_cal_settings,
-        size_t num_streams, struct ma_state *volume_table)
+    const struct ma_audio_cal_settings *audio_cal_settings,
+    size_t num_streams, struct ma_state *volume_table)
 {
-    return my_data->ma_set_volume_table(
-                     g_ma_audio_cal_handle,
-                     audio_cal_settings,
-                     num_streams,
-                     volume_table);
-
+    return my_data->ma_set_volume_table(g_ma_audio_cal_handle,
+                                        audio_cal_settings, num_streams,
+                                        volume_table);
 }
 
 static inline bool valid_usecase(struct audio_usecase *usecase)
@@ -175,7 +165,7 @@
         /* support devices */
         ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
          (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
-         (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
+         /* TODO: enable A2DP when it is ready */
          (usecase->devices & AUDIO_DEVICE_OUT_ALL_USB)))
 
         return true;
@@ -219,7 +209,6 @@
     list_for_each(node, &adev->usecase_list) {
         usecase = node_to_item(node, struct audio_usecase, list);
         if (valid_usecase(usecase)) {
-            ma_cal->platform = adev->platform;
             ma_cal->app_type = usecase->stream.out->app_type_cfg.app_type;
             ma_cal->device = usecase->stream.out->devices;
             ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
@@ -228,7 +217,7 @@
             switch (cmd) {
                 case MA_CMD_VOL:
                     ret = ma_set_volume_table_l(ma_cal, STREAM_MAX_TYPES,
-                                                  ma_cur_state_table);
+                                                ma_cur_state_table);
                     if (ret)
                         ALOGV("Waves: ma_set_volume_table_l success");
                     else
@@ -236,9 +225,9 @@
 
                     ALOGV("%s: send volume table === Start", __func__);
                     for (i = 0; i < STREAM_MAX_TYPES; i++)
-                        ALOGV("%s: stream(%d) volume(%f) active(%s)", __func__, i,
-                            ma_cur_state_table[i].vol,
-                            ma_cur_state_table[i].active ? "T" : "F");
+                        ALOGV("%s: stream(%d) volume(%f) active(%s)", __func__,
+                              i, ma_cur_state_table[i].vol,
+                              ma_cur_state_table[i].active ? "T" : "F");
                     ALOGV("%s: send volume table === End", __func__);
                     break;
                 case MA_CMD_SWAP_ENABLE:
@@ -258,7 +247,6 @@
                 default:
                     ALOGE("%s: unsupported cmd %d", __func__, cmd);
             }
-
         }
     }
     free(ma_cal);
@@ -294,10 +282,14 @@
 
 static void ma_set_swap_l(struct audio_device *adev, bool enable)
 {
+    // do platform LR swap if it enables on Waves effect
+    // but there is no Waves implementation
     if (!my_data) {
-        ALOGE("%s: maxxaudio isn't initialized.", __func__);
+        platform_check_and_set_swap_lr_channels(adev, enable);
+        ALOGV("%s: maxxaudio isn't initialized.", __func__);
         return;
     }
+
     if (enable)
         check_and_send_all_audio_cal(adev, MA_CMD_SWAP_ENABLE);
     else
@@ -316,7 +308,7 @@
         ret = snprintf(path, sizeof(path), "/proc/asound/card%u/id", card);
         if (ret < 0) {
             ALOGE("%s: failed on snprintf (%d) to path %s\n",
-              __func__, ret, path);
+                  __func__, ret, path);
             goto done;
         }
         fd = open(path, O_RDONLY);
@@ -350,7 +342,11 @@
 {
     ma_stream_type_t i = 0;
     int ret = 0;
-    char lib_path[256];
+    char lib_path[128] = {0};
+    char mps_path[128] = {0};
+    char cnf_path[128] = {0};
+    struct snd_card_split *snd_split_handle = NULL;
+    snd_split_handle = audio_extn_get_snd_card_split();
 
     if (platform == NULL) {
         ALOGE("%s: platform is NULL", __func__);
@@ -366,6 +362,7 @@
 
     pthread_mutex_init(&my_data->lock, NULL);
 
+    my_data->platform = platform;
     ret = snprintf(lib_path, sizeof(lib_path), "%s/%s", LIB_MA_PATH, LIB_MA_PARAM);
     if (ret < 0) {
         ALOGE("%s: snprintf failed for lib %s, ret %d", __func__, LIB_MA_PARAM, ret);
@@ -380,71 +377,92 @@
          ALOGV("%s: DLOPEN successful for %s", __func__, LIB_MA_PARAM);
 
          my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle,
-                                     MA_QDSP_PARAM_INIT);
+                                   MA_QDSP_PARAM_INIT);
          if (!my_data->ma_param_init) {
              ALOGE("%s: dlsym error %s for ma_param_init", __func__, dlerror());
              goto error;
          }
 
-         my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(my_data->waves_handle,
-                                       MA_QDSP_PARAM_DEINIT);
+         my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(
+                                     my_data->waves_handle, MA_QDSP_PARAM_DEINIT);
          if (!my_data->ma_param_deinit) {
              ALOGE("%s: dlsym error %s for ma_param_deinit", __func__, dlerror());
              goto error;
          }
 
          my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
-                                      MA_QDSP_SET_LR_SWAP);
+                                    MA_QDSP_SET_LR_SWAP);
          if (!my_data->ma_set_lr_swap) {
              ALOGE("%s: dlsym error %s for ma_set_lr_swap", __func__, dlerror());
              goto error;
          }
 
-         my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(my_data->waves_handle,
-                                         MA_QDSP_SET_MODE);
+         my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(
+                                       my_data->waves_handle, MA_QDSP_SET_MODE);
          if (!my_data->ma_set_sound_mode) {
              ALOGE("%s: dlsym error %s for ma_set_sound_mode", __func__, dlerror());
              goto error;
          }
 
          my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle,
-                                     MA_QDSP_SET_VOL);
+                                   MA_QDSP_SET_VOL);
          if (!my_data->ma_set_volume) {
              ALOGE("%s: dlsym error %s for ma_set_volume", __func__, dlerror());
              goto error;
          }
 
-         my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(my_data->waves_handle,
-                                           MA_QDSP_SET_VOLT);
+         my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(
+                                         my_data->waves_handle, MA_QDSP_SET_VOLT);
          if (!my_data->ma_set_volume_table) {
              ALOGE("%s: dlsym error %s for ma_set_volume_table", __func__, dlerror());
              goto error;
          }
     }
 
-    /* check file */
-    if (access(PRESET_PATH, F_OK) < 0) {
-        ALOGW("%s: file %s isn't existed.", __func__, PRESET_PATH);
-        goto error;
+    /* get preset table */
+    if (snd_split_handle == NULL) {
+        snprintf(mps_path, sizeof(mps_path), "%s/%s.mps",
+                 PRESET_PATH, MPS_BASE_STRING);
+    } else {
+        snprintf(mps_path, sizeof(mps_path), "%s/%s_%s.mps",
+                 PRESET_PATH, MPS_BASE_STRING, snd_split_handle->form_factor);
     }
+
+    /* get config files */
+    if (snd_split_handle == NULL) {
+        snprintf(cnf_path, sizeof(cnf_path), "%s/%s.ini",
+                 PRESET_PATH, CONFIG_BASE_STRING);
+    } else {
+        snprintf(cnf_path, sizeof(cnf_path), "%s/%s_%s.ini",
+                 PRESET_PATH, CONFIG_BASE_STRING, snd_split_handle->form_factor);
+    }
+
+    /* check file */
+    if (access(mps_path, R_OK) < 0) {
+        ALOGW("%s: file %s isn't existed.", __func__, mps_path);
+        goto error;
+    } else
+        ALOGD("%s: Loading mps file: %s", __func__, mps_path);
+
     /* TODO: check user preset table once the feature is enabled
     if (access(USER_PRESET_PATH, F_OK) < 0 ){
         ALOGW("%s: file %s isn't existed.", __func__, USER_PRESET_PATH);
         goto error;
     }
     */
-    if (access(CONFIG_PATH, F_OK) < 0) {
-        ALOGW("%s: file %s isn't existed.", __func__, CONFIG_PATH);
+
+    if (access(cnf_path, R_OK) < 0) {
+        ALOGW("%s: file %s isn't existed.", __func__, cnf_path);
         goto error;
-    }
+    } else
+        ALOGD("%s: Loading ini file: %s", __func__, cnf_path);
 
     /* init ma parameter */
     if (my_data->ma_param_init(&g_ma_audio_cal_handle,
-                                  platform, /* TODO: remove this on next version*/
-                                  PRESET_PATH,
-                                  USER_PRESET_PATH, /* useless */
-                                  CONFIG_PATH,
-                                  &set_audio_cal)) {
+                               mps_path,
+                               USER_PRESET_PATH, /* unused */
+                               cnf_path,
+                               &set_audio_cal)) {
         if (!g_ma_audio_cal_handle) {
             ALOGE("%s: ma parameters initialize failed", __func__);
             my_data->ma_param_deinit(&g_ma_audio_cal_handle);
@@ -487,8 +505,8 @@
 }
 
 // adev_init and adev lock held
-bool audio_extn_ma_set_state(
-        struct audio_device *adev, int stream_type, float vol, bool active)
+bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
+                             float vol, bool active)
 {
     bool ret = false;
     ma_stream_type_t stype = (ma_stream_type_t)stream_type;
@@ -497,7 +515,7 @@
           __func__, stream_type, vol, active ? "true" : "false");
 
     if (!my_data) {
-        ALOGE("%s: maxxaudio isn't initialized.", __func__);
+        ALOGV("%s: maxxaudio isn't initialized.", __func__);
         return ret;
     }
 
@@ -505,7 +523,7 @@
     // 1. start track: active and volume isn't zero
     // 2. stop track: no tracks are active
     if ((active && vol != 0) ||
-         (!active)) {
+        (!active)) {
         pthread_mutex_lock(&my_data->lock);
 
         ma_cur_state_table[stype].vol = vol;
@@ -519,7 +537,7 @@
     return ret;
 }
 
-void audio_extn_ma_set_device(struct audio_device *adev, struct audio_usecase *usecase)
+void audio_extn_ma_set_device(struct audio_usecase *usecase)
 {
     int i = 0;
     int u_index = -1;
@@ -540,7 +558,6 @@
 
     /* update audio_cal and send it */
     if (ma_cal != NULL){
-        ma_cal->platform = adev->platform;
         ma_cal->app_type = usecase->stream.out->app_type_cfg.app_type;
         ma_cal->device = usecase->stream.out->devices;
         ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
@@ -557,8 +574,8 @@
             ALOGV("%s: send volume table === End", __func__);
 
             if (!ma_set_volume_table_l(ma_cal,
-                                         STREAM_MAX_TYPES,
-                                         ma_cur_state_table))
+                                       STREAM_MAX_TYPES,
+                                       ma_cur_state_table))
                 ALOGE("Waves: ma_set_volume_table_l %f returned with error.", vol);
             else
                 ALOGV("Waves: ma_set_volume_table_l success");
@@ -571,7 +588,8 @@
     }
 }
 
-void audio_extn_ma_set_parameters(struct audio_device *adev, struct str_parms *parms)
+void audio_extn_ma_set_parameters(struct audio_device *adev,
+                                  struct str_parms *parms)
 {
     int ret;
     bool ret_b;
@@ -594,7 +612,8 @@
     }
 
     // check connect status
-    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
+                            sizeof(value));
     if (ret >= 0) {
         audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
         if (audio_is_usb_out_device(device)) {
@@ -607,7 +626,8 @@
     }
 
     // check disconnect status
-    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
+                            sizeof(value));
     if (ret >= 0) {
         audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
         if (audio_is_usb_out_device(device)) {
diff --git a/hal/audio_extn/maxxaudio.h b/hal/audio_extn/maxxaudio.h
index a2ebaed..4c91107 100644
--- a/hal/audio_extn/maxxaudio.h
+++ b/hal/audio_extn/maxxaudio.h
@@ -18,18 +18,20 @@
 #define MAXXAUDIO_H_
 
 #ifndef MAXXAUDIO_QDSP_ENABLED
-#define audio_extn_ma_init(platform)                                      (0)
-#define audio_extn_ma_deinit()                                            (0)
-#define audio_extn_ma_set_state(adev, type, vol, active)                  (false)
-#define audio_extn_ma_set_device(adev, usecase)                           (0)
-#define audio_extn_ma_set_parameters(adev, param)                         (0)
-#define audio_extn_ma_supported_usb()                                     (false)
+#define audio_extn_ma_init(platform)                                (0)
+#define audio_extn_ma_deinit()                                      (0)
+#define audio_extn_ma_set_state(adev, type, vol, active)            (false)
+#define audio_extn_ma_set_device(usecase)                           (0)
+#define audio_extn_ma_set_parameters(adev, param)                   (0)
+#define audio_extn_ma_supported_usb()                               (false)
 #else
 void audio_extn_ma_init(void *platform);
 void audio_extn_ma_deinit();
-bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type, float vol, bool active);
-void audio_extn_ma_set_device(struct audio_device *adev, struct audio_usecase *usecase);
-void audio_extn_ma_set_parameters(struct audio_device *adev, struct str_parms *parms);
+bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
+                             float vol, bool active);
+void audio_extn_ma_set_device(struct audio_usecase *usecase);
+void audio_extn_ma_set_parameters(struct audio_device *adev,
+                                  struct str_parms *parms);
 bool audio_extn_ma_supported_usb();
 #endif /* MAXXAUDIO_QDSP_ENABLED */
 
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 2518e3d..f8c5563 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -78,7 +78,6 @@
 
 #include "sound/compress_params.h"
 #include "sound/asound.h"
-#include "audio_extn/maxxaudio.h"
 
 #ifdef DYNAMIC_LOG_ENABLED
 #include <log_xml_parser.h>
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index ca1ba15..37eae22 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -45,7 +45,6 @@
 #include "edid.h"
 #include "sound/compress_params.h"
 #include "sound/msmcal-hwdep.h"
-#include "maxxaudio.h"
 
 #ifdef DYNAMIC_LOG_ENABLED
 #include <log_xml_parser.h>
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 1968074..44d4a74 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -136,7 +136,6 @@
     SND_DEVICE_OUT_SPEAKER_SAFE_AND_USB_HEADSET,
     SND_DEVICE_OUT_VOICE_USB_HEADPHONES,
     SND_DEVICE_OUT_VOICE_USB_HEADSET,
-    /* Specific snd_devices */
     SND_DEVICE_OUT_USB_HEADSET_SPEC,
     SND_DEVICE_OUT_TRANSMISSION_FM,
     SND_DEVICE_OUT_ANC_HEADSET,
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 4fa1573..fcaf378 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -220,14 +220,14 @@
 LOCAL_CFLAGS := -D HAL_LIB_NAME=\"audio.primary."$(TARGET_BOARD_PLATFORM)".so\"
 
 LOCAL_SRC_FILES:= \
-	ma_listener.c
+    ma_listener.c
 
 LOCAL_CFLAGS += $(qcom_post_proc_common_cflags)
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	liblog \
-	libdl
+    libcutils \
+    liblog \
+    libdl
 
 LOCAL_MODULE_RELATIVE_PATH := soundfx
 LOCAL_MODULE:= libmalistener
@@ -235,9 +235,9 @@
 LOCAL_PROPRIETARY_MODULE := true
 
 LOCAL_C_INCLUDES := \
-	hardware/qcom/audio/hal \
-	system/media/audio/include/system \
-	$(call include-path-for, audio-effects)
+    hardware/qcom/audio/hal \
+    system/media/audio/include/system \
+    $(call include-path-for, audio-effects)
 
 LOCAL_HEADER_LIBRARIES += libhardware_headers
 LOCAL_HEADER_LIBRARIES += libsystem_headers
diff --git a/post_proc/ma_listener.c b/post_proc/ma_listener.c
index 8e57db1..02d45d3 100644
--- a/post_proc/ma_listener.c
+++ b/post_proc/ma_listener.c
@@ -61,7 +61,7 @@
 
 static const audio_stream_type_t MIN_STREAM_TYPES = AUDIO_STREAM_VOICE_CALL;
 static const audio_stream_type_t MAX_STREAM_TYPES = AUDIO_STREAM_NOTIFICATION;
-static struct ma_state g_cur_state[MAX_STREAM_TYPES];
+static struct ma_state g_cur_state[MAX_STREAM_TYPES + 1];
 
 struct ma_listener_context_s {
     const struct effect_interface_s *itfe;
@@ -211,6 +211,8 @@
     else if (max_vol > 1.0) max_vol = 1.0;
 
     if (send_ma_parameter != NULL &&
+        stream_type >= MIN_STREAM_TYPES &&
+        stream_type <= MAX_STREAM_TYPES &&
         (g_cur_state[stream_type].vol != max_vol ||
          g_cur_state[stream_type].active != active)) {