Merge "post_proc: fix noise at start of multichannel playback in hw_acc mode"
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 8601a7e..f51cfa7 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -58,6 +58,10 @@
 #define SAFE_SPKR_TEMP 40
 #define SAFE_SPKR_TEMP_Q6 (SAFE_SPKR_TEMP * (1 << 6))
 
+/*Bongo Spkr temp range*/
+#define TZ_TEMP_MIN_THRESHOLD    (5)
+#define TZ_TEMP_MAX_THRESHOLD    (45)
+
 /*Range of resistance values 2ohms to 40 ohms*/
 #define MIN_RESISTANCE_SPKR_Q24 (2 * (1 << 24))
 #define MAX_RESISTANCE_SPKR_Q24 (40 * (1 << 24))
@@ -214,7 +218,8 @@
             snprintf(name, MAX_PATH, TZ_TYPE, tzn);
             ALOGD("Opening %s\n", name);
             read_line_from_file(name, buf, sizeof(buf));
-            buf[strlen(buf)] = '\0';
+            if (strlen(buf) > 0)
+                buf[strlen(buf) - 1] = '\0';
             if (!strcmp(buf, sensor_name)) {
                 found = 1;
                 break;
@@ -726,24 +731,23 @@
         close(acdb_fd);
     }
 
+    ALOGV("%s: start calibration", __func__);
     while (1) {
-        ALOGV("%s: start calibration", __func__);
         if (handle.wsa_found) {
             spk_1_tzn = handle.spkr_1_tzn;
             spk_2_tzn = handle.spkr_2_tzn;
             goahead = false;
             pthread_mutex_lock(&adev->lock);
             if (is_speaker_in_use(&sec)) {
-                ALOGD("%s: WSA Speaker in use retry calibration", __func__);
+                ALOGV("%s: WSA Speaker in use retry calibration", __func__);
                 pthread_mutex_unlock(&adev->lock);
                 continue;
             } else {
-                ALOGD("%s: wsa speaker idle %ld min time %ld", __func__, sec, min_idle_time);
                 if (sec < min_idle_time) {
-                    ALOGD("%s: speaker idle is less retry", __func__);
                     pthread_mutex_unlock(&adev->lock);
                     continue;
                }
+               ALOGV("%s: wsa speaker idle %ld min time %ld", __func__, sec, min_idle_time);
                goahead = true;
            }
            if (!list_empty(&adev->usecase_list)) {
@@ -753,7 +757,7 @@
            if (goahead) {
                if (spk_1_tzn >= 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_1_tzn);
-                   ALOGD("%s: wsa_path: %s\n", __func__, wsa_path);
+                   ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
                    thermal_fd = -1;
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
@@ -777,18 +781,24 @@
                        ALOGE("%s: fd for %s is NULL\n", __func__, wsa_path);
                    }
                    if (i == NUM_ATTEMPTS) {
+                       if (t0_spk_1 < TZ_TEMP_MIN_THRESHOLD ||
+                           t0_spk_1 > TZ_TEMP_MAX_THRESHOLD) {
+                           pthread_mutex_unlock(&adev->lock);
+                           continue;
+                       }
                        /*Convert temp into q6 format*/
                        t0_spk_1 = (t0_spk_1 * (1 << 6));
                        ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
                    } else {
-                       ALOGD("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
+                       ALOGV("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
                                                 __func__, i, NUM_ATTEMPTS);
-                       t0_spk_1 = SAFE_SPKR_TEMP_Q6;
+                       pthread_mutex_unlock(&adev->lock);
+                       continue;
                    }
                }
                if (spk_2_tzn >= 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
-                   ALOGD("%s: wsa_path: %s\n", __func__, wsa_path);
+                   ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
                        for (i = 0; i < NUM_ATTEMPTS; i++) {
@@ -811,13 +821,19 @@
                        ALOGE("%s: fd for %s is NULL\n", __func__, wsa_path);
                    }
                    if (i == NUM_ATTEMPTS) {
+                       if (t0_spk_2 < TZ_TEMP_MIN_THRESHOLD ||
+                           t0_spk_2 > TZ_TEMP_MAX_THRESHOLD) {
+                           pthread_mutex_unlock(&adev->lock);
+                           continue;
+                       }
                        /*Convert temp into q6 format*/
                        t0_spk_2 = (t0_spk_2 * (1 << 6));
                        ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
                    } else {
-                       ALOGE("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
+                       ALOGV("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
                                                 __func__, i, NUM_ATTEMPTS);
-                       t0_spk_2 = SAFE_SPKR_TEMP_Q6;
+                       pthread_mutex_unlock(&adev->lock);
+                       continue;
                    }
                }
            }
@@ -848,16 +864,15 @@
         goahead = false;
         pthread_mutex_lock(&adev->lock);
         if (is_speaker_in_use(&sec)) {
-            ALOGD("%s: Speaker in use retry calibration", __func__);
+            ALOGV("%s: Speaker in use retry calibration", __func__);
             pthread_mutex_unlock(&adev->lock);
             continue;
         } else {
-            ALOGD("%s: speaker idle %ld min time %ld", __func__, sec, min_idle_time);
             if (sec < min_idle_time) {
-                ALOGD("%s: speaker idle is less retry", __func__);
                 pthread_mutex_unlock(&adev->lock);
                 continue;
             }
+            ALOGD("%s: speaker idle %ld min time %ld", __func__, sec, min_idle_time);
             goahead = true;
         }
         if (!list_empty(&adev->usecase_list)) {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 4bc6b59..e50e1b6 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -718,7 +718,8 @@
         if (usecase->type != PCM_PLAYBACK &&
                 usecase != uc_info &&
                 usecase->in_snd_device != snd_device &&
-                (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+                ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+                ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
                 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
             ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
                   __func__, use_case_table[usecase->id],
@@ -2802,7 +2803,8 @@
     out->use_small_bufs = false;
 
     /* Init use case and pcm_config */
-    if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
+    if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
+        !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
         (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
         out->devices & AUDIO_DEVICE_OUT_PROXY)) {
 
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 3a8f314..02cb673 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1237,6 +1237,10 @@
     const char *snd_card_name;
     char mixer_xml_path[100],ffspEnable[PROPERTY_VALUE_MAX];
     char *cvd_version = NULL;
+    int idx;
+
+    my_data = calloc(1, sizeof(struct platform_data));
+
     if (!my_data) {
         ALOGE("failed to allocate platform data");
         return NULL;
@@ -1760,7 +1764,7 @@
 {
     if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
         ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
-        return DEFAULT_OUTPUT_SAMPLING_RATE;
+        return CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     }
     return backend_bit_width_table[snd_device];
 }
@@ -3695,6 +3699,16 @@
             sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         }
     }
+
+    /*
+     * Sample rate greater than 48K is only supported by external codecs on
+     * specific devices e.g. Headphones, reset the sample rate to
+     * default value if not external codec.
+     */
+    if (!is_external_codec)
+        sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+
+
     ALOGI("%s Codec selected backend: %d updated bit width: %d and sample rate: %d",
                __func__, backend_idx, bit_width, sample_rate);
     // Force routing if the expected bitwdith or samplerate
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index c63bfe9..af2f6ae 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -47,6 +47,15 @@
     (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
      AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
 
+/*
+ * Below are the input devices for which back end is same, SLIMBUS_0_TX.
+ * All these devices are handled by the internal HW codec. We can
+ * enable any one of these devices at any time
+ */
+#define AUDIO_DEVICE_IN_ALL_CODEC_BACKEND \
+    (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC | \
+     AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_VOICE_CALL) & ~AUDIO_DEVICE_BIT_IN
+
 /* Sound devices specific to the platform
  * The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
  * devices to enable corresponding mixer paths
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 4b4d14e..aab5436 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2015 The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -35,6 +35,15 @@
     (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
      AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
 
+/*
+ * Below are the input devices for which back end is same, SLIMBUS_0_TX.
+ * All these devices are handled by the internal HW codec. We can
+ * enable any one of these devices at any time
+ */
+#define AUDIO_DEVICE_IN_ALL_CODEC_BACKEND \
+    (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC | \
+     AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_VOICE_CALL) & ~AUDIO_DEVICE_BIT_IN
+
 /* Sound devices specific to the platform
  * The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
  * devices to enable corresponding mixer paths
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index 7849644..73bc779 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -175,6 +175,34 @@
     SND_DEVICE_OUT_VOICE_SPEAKER,
 };
 
+static const snd_device_t tasha_fluid_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+    SND_DEVICE_OUT_VOICE_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+    SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET,
+    SND_DEVICE_OUT_SPEAKER_PROTECTED,
+    SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+};
+
+static const snd_device_t tasha_liquid_variant_devices[] = {
+    SND_DEVICE_OUT_SPEAKER,
+    SND_DEVICE_OUT_SPEAKER_EXTERNAL_1,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+    SND_DEVICE_IN_SPEAKER_MIC,
+    SND_DEVICE_IN_HEADSET_MIC,
+    SND_DEVICE_IN_VOICE_DMIC,
+    SND_DEVICE_IN_VOICE_SPEAKER_DMIC,
+    SND_DEVICE_IN_VOICE_REC_DMIC_STEREO,
+    SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE,
+    SND_DEVICE_IN_QUAD_MIC,
+    SND_DEVICE_IN_HANDSET_STEREO_DMIC,
+    SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
+};
+
 static void  update_hardware_info_8084(struct hardware_info *hw_info, const char *snd_card_name)
 {
     if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card") ||
@@ -270,18 +298,24 @@
         hw_info->snd_devices = (snd_device_t *)tomtom_8996_CDP_variant_devices;
         hw_info->num_snd_devices = ARRAY_SIZE(tomtom_8996_CDP_variant_devices);
         strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn));
-    } else if (!strcmp(snd_card_name, "msm8996-tomtom-stp-snd-card")) {
-        strlcpy(hw_info->type, " stp", sizeof(hw_info->type));
-        strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
-        hw_info->snd_devices = (snd_device_t *)tomtom_stp_variant_devices;
-        hw_info->num_snd_devices = ARRAY_SIZE(tomtom_stp_variant_devices);
-        strlcpy(hw_info->dev_extn, "-stp", sizeof(hw_info->dev_extn));
     } else if (!strcmp(snd_card_name, "msm8996-tomtom-liquid-snd-card")) {
         strlcpy(hw_info->type, " liquid", sizeof(hw_info->type));
         strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
         hw_info->snd_devices = (snd_device_t *)tomtom_liquid_variant_devices;
         hw_info->num_snd_devices = ARRAY_SIZE(tomtom_liquid_variant_devices);
         strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8996-tasha-fluid-snd-card")) {
+        strlcpy(hw_info->type, " fluid", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
+        hw_info->snd_devices = (snd_device_t *)tasha_fluid_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tasha_fluid_variant_devices);
+        strlcpy(hw_info->dev_extn, "-fluid", sizeof(hw_info->dev_extn));
+    } else if (!strcmp(snd_card_name, "msm8996-tasha-liquid-snd-card")) {
+        strlcpy(hw_info->type, " liquid", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
+        hw_info->snd_devices = (snd_device_t *)tasha_liquid_variant_devices;
+        hw_info->num_snd_devices = ARRAY_SIZE(tasha_liquid_variant_devices);
+        strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn));
     } else if (!strcmp(snd_card_name, "msm8996-tasha-db-snd-card")) {
         strlcpy(hw_info->type, " dragon-board", sizeof(hw_info->type));
         strlcpy(hw_info->name, "msm8996", sizeof(hw_info->name));
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 875cc2c..e617c0e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1040,40 +1040,55 @@
     void   *buff;
 };
 
-static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
+static void send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
 {
-    int ret = 0, type;
+    int type;
 
     for (type = WCD9XXX_ANC_CAL; type < WCD9XXX_MAX_CAL; type++) {
         struct wcdcal_ioctl_buffer codec_buffer;
         struct param_data calib;
+        int ret;
 
+        ret = 0;
         calib.get_size = 1;
-        ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
-                                                                 &calib);
+        ret = acdb_loader_get_calibration(cal_name_info[type],
+                                          sizeof(struct param_data),
+                                          &calib);
         if (ret < 0) {
-            ALOGE("%s get_calibration failed\n", __func__);
-            return ret;
+            ALOGE("%s: %s get_calibration size failed, err = %d\n",
+                  __func__, cal_name_info[type], ret);
+            continue;
         }
+
         calib.get_size = 0;
         calib.buff = malloc(calib.buff_size);
+        if (!calib.buff) {
+            ALOGE("%s: %s: No Memory for size = %d\n",
+                  __func__, cal_name_info[type], calib.buff_size);
+            continue;
+        }
+
         ret = acdb_loader_get_calibration(cal_name_info[type],
                               sizeof(struct param_data), &calib);
         if (ret < 0) {
-            ALOGE("%s get_calibration failed\n", __func__);
+            ALOGE("%s: %s get_calibration failed, err = %d\n",
+                  __func__, cal_name_info[type], ret);
             free(calib.buff);
-            return ret;
+            continue;
         }
+
         codec_buffer.buffer = calib.buff;
         codec_buffer.size = calib.data_size;
         codec_buffer.cal_type = type;
         if (ioctl(fd, SNDRV_CTL_IOCTL_HWDEP_CAL_TYPE, &codec_buffer) < 0)
-            ALOGE("Failed to call ioctl  for %s err=%d",
-                                  cal_name_info[type], errno);
-        ALOGD("%s cal sent for %s", __func__, cal_name_info[type]);
+            ALOGE("%s: %s Failed to call ioctl, err=%d",
+                  __func__, cal_name_info[type], errno);
+        else
+            ALOGD("%s: %s cal sent successfully\n",
+              __func__, cal_name_info[type]);
+
         free(calib.buff);
     }
-    return ret;
 }
 
 static void audio_hwdep_send_cal(struct platform_data *plat_data)
@@ -1094,8 +1109,8 @@
            dlerror());
         return;
     }
-    if (send_codec_cal(acdb_loader_get_calibration, fd) < 0)
-        ALOGE("%s: Could not send anc cal", __FUNCTION__);
+
+    send_codec_cal(acdb_loader_get_calibration, fd);
 }
 
 static int platform_acdb_init(void *platform)
@@ -1827,11 +1842,10 @@
     int snd_device = SND_DEVICE_OUT_SPEAKER;
 
     if (usecase->type == PCM_PLAYBACK)
-        snd_device = platform_get_output_snd_device(adev->platform,
-                                            usecase->stream.out);
+        snd_device =  usecase->out_snd_device;
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
-        snd_device = platform_get_input_snd_device(adev->platform,
-                                            adev->primary_output->devices);
+        snd_device = usecase->in_snd_device;
+
     acdb_dev_id = acdb_device_table[audio_extn_get_spkr_prot_snd_device(snd_device)];
     if (acdb_dev_id < 0) {
         ALOGE("%s: Could not find acdb id for device(%d)",
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 2247933..fa9f4bb 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -45,6 +45,15 @@
     (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
      AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
 
+/*
+ * Below are the input devices for which back end is same, SLIMBUS_0_TX.
+ * All these devices are handled by the internal HW codec. We can
+ * enable any one of these devices at any time
+ */
+#define AUDIO_DEVICE_IN_ALL_CODEC_BACKEND \
+    (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC | \
+     AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_VOICE_CALL) & ~AUDIO_DEVICE_BIT_IN
+
 /* Sound devices specific to the platform
  * The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
  * devices to enable corresponding mixer paths
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index 2748568..3874f0b 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -56,6 +56,15 @@
     ALOGV("%s: ctxt %p, strength: %d", __func__, context, strength);
     context->strength = strength;
 
+    /*
+     *  Zero strength is not equivalent to disable state as down mix
+     *  is still happening for multichannel inputs.
+     *  For better user experience, explicitly disable virtualizer module
+     *  when strength is 0.
+     */
+    offload_virtualizer_set_enable_flag(&(context->offload_virt),
+                                        ((strength > 0) && !(context->temp_disabled)) ?
+                                        true : false);
     offload_virtualizer_set_strength(&(context->offload_virt), strength);
     if (context->ctl)
         offload_virtualizer_send_params(context->ctl, &context->offload_virt,