Merge "hal: Fix voice call routing issue on headset"
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index efc2307..0ef7c7e 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -251,7 +251,7 @@
                  * Currently, platform_get_wsa_mode will directly return
                  * 1 when wsa is in analog mode.
                  */
-                if (platform_get_wsa_mode(adev->platform) == 1) {
+                if (platform_get_wsa_mode(adev) == 1) {
                     fm_stop(adev);
                     fm_start(adev);
                 } else {
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 391a501..b7217d6 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))
@@ -485,6 +489,7 @@
     enable_audio_route(adev, uc_info_tx);
 
     pcm_dev_tx_id = platform_get_pcm_device_id(uc_info_tx->id, PCM_CAPTURE);
+    ALOGV("%s: pcm device id %d", __func__, pcm_dev_tx_id);
     if (pcm_dev_tx_id < 0) {
         ALOGE("%s: Invalid pcm device for usecase (%d)",
               __func__, uc_info_tx->id);
@@ -647,6 +652,7 @@
     char wsa_path[MAX_PATH] = {0};
     int spk_1_tzn, spk_2_tzn;
     char buf[32] = {0};
+    int ret;
 
     /* If the value of this persist.spkr.cal.duration is 0
      * then it means it will take 30min to calibrate
@@ -724,24 +730,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)) {
@@ -751,18 +756,22 @@
            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) {
                        for (i = 0; i < NUM_ATTEMPTS; i++) {
-                            if (read(thermal_fd, buf, sizeof(buf))) {
+                            if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
                                 t0_spk_1 = atoi(buf);
-                                if (i > 0 && (t0_spk_1 != t0_spk_prior))
+                                if (i > 0 && (t0_spk_1 != t0_spk_prior)) {
+                                    ALOGE("%s: spkr1 curr temp: %d, prev temp: %d\n",
+                                          __func__, t0_spk_1, t0_spk_prior);
                                     break;
+                                }
                                 t0_spk_prior = t0_spk_1;
+                                sleep(1);
                             } else {
-                               ALOGE("%s: read fail for %s\n", __func__, wsa_path);
+                               ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
                                break;
                             }
                         }
@@ -771,28 +780,38 @@
                        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));
-                       ALOGE("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
+                       ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
                    } else {
-                       ALOGE("%s: thermal equilibrium failed for spkr1 in %d readings\n",
-                                                __func__, NUM_ATTEMPTS);
-                       t0_spk_1 = SAFE_SPKR_TEMP_Q6;
+                       ALOGV("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
+                                                __func__, i, NUM_ATTEMPTS);
+                       pthread_mutex_unlock(&adev->lock);
+                       continue;
                    }
                }
                if (spk_2_tzn > 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
-                   ALOGE("%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++) {
-                            if (read(thermal_fd, buf, sizeof(buf))) {
+                            if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
                                 t0_spk_2 = atoi(buf);
-                                if (i > 0 && (t0_spk_2 != t0_spk_prior))
+                                if (i > 0 && (t0_spk_2 != t0_spk_prior)) {
+                                    ALOGE("%s: spkr2 curr temp: %d, prev temp: %d\n",
+                                          __func__, t0_spk_2, t0_spk_prior);
                                     break;
+                                }
                                 t0_spk_prior = t0_spk_2;
+                                sleep(1);
                             } else {
-                               ALOGE("%s: read fail for %s\n", __func__, wsa_path);
+                               ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
                                break;
                             }
                         }
@@ -801,13 +820,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));
-                       ALOGE("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
+                       ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
                    } else {
-                       ALOGE("%s: thermal equilibrium failed for spkr2 in %d readings\n",
-                                                __func__, NUM_ATTEMPTS);
-                       t0_spk_2 = SAFE_SPKR_TEMP_Q6;
+                       ALOGV("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
+                                                __func__, i, NUM_ATTEMPTS);
+                       pthread_mutex_unlock(&adev->lock);
+                       continue;
                    }
                }
            }
@@ -838,16 +863,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)) {
@@ -925,6 +949,12 @@
     handle.spkr_prot_t0 = -1;
 
     if (is_wsa_present()) {
+        if (platform_get_wsa_mode(adev) == 1) {
+            ALOGD("%s: WSA analog mode", __func__);
+            platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED, 136);
+            platform_set_snd_device_acdb_id(SND_DEVICE_IN_CAPTURE_VI_FEEDBACK, 137);
+            pcm_config_skr_prot.channels = 2;
+        }
         pthread_cond_init(&handle.spkr_calib_cancel, NULL);
         pthread_cond_init(&handle.spkr_calibcancel_ack, NULL);
         pthread_mutex_init(&handle.mutex_spkr_prot, NULL);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index f97efdd..9f27219 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -486,7 +486,7 @@
     if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
        audio_extn_usb_start_capture(adev);
 
-    if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
+    if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
         snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
         audio_extn_spkr_prot_is_enabled()) {
        if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
@@ -556,7 +556,7 @@
         if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
             audio_extn_usb_stop_capture();
 
-        if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
+        if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
             snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
             audio_extn_spkr_prot_is_enabled()) {
             audio_extn_spkr_prot_stop_processing(snd_device);
@@ -694,7 +694,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],
@@ -2883,7 +2884,7 @@
         }
         out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
         out->compr_config.codec->sample_rate =
-                    compress_get_alsa_rate(config->offload_info.sample_rate);
+                    config->offload_info.sample_rate;
         out->compr_config.codec->bit_rate =
                     config->offload_info.bit_rate;
         out->compr_config.codec->ch_in =
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index fb36a95..613c1a7 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -257,6 +257,12 @@
         hw_info->snd_devices = NULL;
         hw_info->num_snd_devices = 0;
         strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
+    }  else if (!strcmp(snd_card_name, "msm8976-skun-snd-card")) {
+        strlcpy(hw_info->type, "", sizeof(hw_info->type));
+        strlcpy(hw_info->name, "msm8976", sizeof(hw_info->name));
+        hw_info->snd_devices = NULL;
+        hw_info->num_snd_devices = 0;
+        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
     } else {
         ALOGW("%s: Not an  8x16/8939/8909/8952 device", __func__);
     }
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index e2a9648..03476e4 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -924,7 +924,9 @@
         msm_be_id_array_len  =
             sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_external_codec[0]);
     } else if (!strncmp(snd_card_name, "msm8952-skum-snd-card",
-                 sizeof("msm8952-skum-snd-card"))) {
+                 sizeof("msm8952-skum-snd-card")) ||
+               !strncmp(snd_card_name, "msm8976-skun-snd-card",
+                 sizeof("msm8976-skun-snd-card"))) {
         strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUM,
                 sizeof(MIXER_XML_PATH_SKUM));
         msm_device_to_be_id = msm_device_to_be_id_internal_codec;
@@ -4504,13 +4506,14 @@
     return ret;
 }
 
-int platform_get_wsa_mode(void *platform)
+int platform_get_wsa_mode(void *adev)
 {
-    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev_h = adev;
     char *snd_card_name;
 
-    snd_card_name = mixer_get_name(my_data->adev->mixer);
+    snd_card_name = mixer_get_name(adev_h->mixer);
     if ((!strcmp(snd_card_name, "msm8952-skum-snd-card")) ||
+        (!strcmp(snd_card_name, "msm8952-snd-card")) ||
         (!strcmp(snd_card_name, "msm8952-snd-card-mtp")))
         return 1;
     else
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 9f0015a..82c01db 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.c b/hal/msm8960/platform.c
index 6212f23..7be3011 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1176,7 +1176,7 @@
     return -ENOSYS;
 }
 
-int platform_get_wsa_mode(void *platform)
+int platform_get_wsa_mode(void *adev)
 {
     return 0;
 }
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/platform.c b/hal/msm8974/platform.c
index 019a889..5b1cebc 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -4093,7 +4093,7 @@
     return ret;
 }
 
-int platform_get_wsa_mode (void *platform)
+int platform_get_wsa_mode (void *adev)
 {
     return 0;
 }
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 4b90f8b..79e0816 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/hal/platform_api.h b/hal/platform_api.h
index d8fa8fa..0b59d78 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -121,5 +121,5 @@
                                        const char *spkr_1_tz_name, const char *spkr_2_tz_name);
 const char *platform_get_spkr_1_tz_name(snd_device_t snd_device);
 const char *platform_get_spkr_2_tz_name(snd_device_t snd_device);
-int platform_get_wsa_mode(void *platform);
+int platform_get_wsa_mode(void *adev);
 #endif // AUDIO_PLATFORM_API_H