Merge "audiopolicy: do not set FM volume during device connection/disconnection" into av-userspace.lnx.1.0-dev.1.0
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 10693ea..123752a 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -210,15 +210,19 @@
 #endif
 
 #ifndef HW_VARIANTS_ENABLED
-#define hw_info_init(snd_card_name)                  (0)
-#define hw_info_deinit(hw_info)                      (0)
+#define hw_info_init(snd_card_name)                      (0)
+#define hw_info_deinit(hw_info)                          (0)
 #define hw_info_append_hw_type(hw_info,\
-        snd_device, device_name)                     (0)
+        snd_device, device_name)                         (0)
+#define hw_info_enable_wsa_combo_usecase_support(hw_info)   (0)
+
 #else
 void *hw_info_init(const char *snd_card_name);
 void hw_info_deinit(void *hw_info);
 void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device,
                              char *device_name);
+void hw_info_enable_wsa_combo_usecase_support(void *hw_info);
+
 #endif
 
 #ifndef AUDIO_LISTEN_ENABLED
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index fdfbfad..2a246cd 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -66,9 +66,6 @@
 #define MIN_RESISTANCE_SPKR_Q24 (2 * (1 << 24))
 #define MAX_RESISTANCE_SPKR_Q24 (40 * (1 << 24))
 
-/*Number of Attempts for WSA equilibrium t0 reads*/
-#define NUM_ATTEMPTS 5
-
 /*Path where the calibration file will be stored*/
 #define CALIB_FILE "/data/misc/audio/audio.cal"
 
@@ -646,7 +643,6 @@
     int i = 0;
     int t0_spk_1 = 0;
     int t0_spk_2 = 0;
-    int t0_spk_prior = 0;
     bool goahead = false;
     struct audio_cal_info_spk_prot_cfg protCfg;
     FILE *fp;
@@ -769,92 +765,46 @@
                    thermal_fd = -1;
                    thermal_fd = open(wsa_path, O_RDONLY);
                    if (thermal_fd > 0) {
-                       for (i = 0; i < NUM_ATTEMPTS; i++) {
-                            if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
-                                t0_spk_1 = atoi(buf);
-                                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;
-                                pthread_mutex_unlock(&adev->lock);
-                                sleep(1);
-                                pthread_mutex_lock(&adev->lock);
-                                if (is_speaker_in_use(&sec))
-                                    break;
-                            } else {
-                               ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
-                               break;
-                            }
-                        }
-                        close(thermal_fd);
+                       if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0)
+                            t0_spk_1 = atoi(buf);
+                       else
+                           ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
+                       close(thermal_fd);
                    } else {
                        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);
-                           sleep(WAKEUP_MIN_IDLE_CHECK);
-                           continue;
-                       }
-                       ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
-                       /*Convert temp into q6 format*/
-                       t0_spk_1 = (t0_spk_1 * (1 << 6));
-                   } else {
-                       ALOGV("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
-                                                __func__, i, NUM_ATTEMPTS);
+                   if (t0_spk_1 < TZ_TEMP_MIN_THRESHOLD ||
+                       t0_spk_1 > TZ_TEMP_MAX_THRESHOLD) {
                        pthread_mutex_unlock(&adev->lock);
                        sleep(WAKEUP_MIN_IDLE_CHECK);
                        continue;
                    }
+                   ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
+                   /*Convert temp into q6 format*/
+                   t0_spk_1 = (t0_spk_1 * (1 << 6));
                }
                if (spk_2_tzn >= 0) {
                    snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
                    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 ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
-                                t0_spk_2 = atoi(buf);
-                                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;
-                                pthread_mutex_unlock(&adev->lock);
-                                sleep(1);
-                                pthread_mutex_lock(&adev->lock);
-                                if (is_speaker_in_use(&sec))
-                                    break;
-                            } else {
-                               ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
-                               break;
-                            }
-                        }
-                        close(thermal_fd);
+                       if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0)
+                           t0_spk_2 = atoi(buf);
+                       else
+                           ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
+                       close(thermal_fd);
                    } else {
                        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);
-                           sleep(WAKEUP_MIN_IDLE_CHECK);
-                           continue;
-                       }
-                       ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
-                       /*Convert temp into q6 format*/
-                       t0_spk_2 = (t0_spk_2 * (1 << 6));
-                   } else {
-                       ALOGV("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
-                                                __func__, i, NUM_ATTEMPTS);
+                   if (t0_spk_2 < TZ_TEMP_MIN_THRESHOLD ||
+                       t0_spk_2 > TZ_TEMP_MAX_THRESHOLD) {
                        pthread_mutex_unlock(&adev->lock);
                        sleep(WAKEUP_MIN_IDLE_CHECK);
                        continue;
                    }
+                   ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
+                   /*Convert temp into q6 format*/
+                   t0_spk_2 = (t0_spk_2 * (1 << 6));
                }
            }
            pthread_mutex_unlock(&adev->lock);
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index 6140698..fb8d648 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -47,9 +47,11 @@
     uint32_t num_snd_devices;
     char dev_extn[HW_INFO_ARRAY_MAX_SIZE];
     snd_device_t  *snd_devices;
+    bool is_wsa_combo_suppported;
 };
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define WSA_MIXER_PATH_EXTENSION "wsa-"
 
 static const snd_device_t taiko_fluid_variant_devices[] = {
     SND_DEVICE_OUT_SPEAKER,
@@ -123,6 +125,14 @@
     SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
 };
 
+static const snd_device_t wsa_combo_devices[] = {
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+    SND_DEVICE_OUT_SPEAKER_AND_LINE,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
+    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2,
+    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET
+};
+
 static void update_hardware_info_8x16(struct hardware_info *hw_info, const char *snd_card_name)
 {
     if (!strcmp(snd_card_name, "msm8x16-snd-card")) {
@@ -332,6 +342,8 @@
     } else {
         ALOGW("%s: Not an  8x16/8939/8909/8952 device", __func__);
     }
+
+    hw_info->is_wsa_combo_suppported = false;
 }
 
 void *hw_info_init(const char *snd_card_name)
@@ -363,19 +375,52 @@
 {
     struct hardware_info *my_data = (struct hardware_info*) hw_info;
 
-    if(!my_data)
+    if(my_data != NULL)
         free(my_data);
 }
 
+void hw_info_enable_wsa_combo_usecase_support(void *hw_info)
+{
+    struct hardware_info *my_data = (struct hardware_info*) hw_info;
+    if(!my_data) {
+        ALOGE(" ERROR wsa combo update is called with invalid hw_info");
+        return;
+    }
+    my_data->is_wsa_combo_suppported = true;
+
+}
+
 void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device,
                             char *device_name)
 {
     struct hardware_info *my_data = (struct hardware_info*) hw_info;
     uint32_t i = 0;
 
+    if(!my_data) {
+        ALOGE(" ERROR hw_info_append_hw_type is called with invalid hw_info");
+        return;
+    }
+
     snd_device_t *snd_devices =
             (snd_device_t *) my_data->snd_devices;
 
+
+    if(my_data->is_wsa_combo_suppported) {
+        for (i = 0; i < ARRAY_SIZE(wsa_combo_devices) ; i++) {
+            if (snd_device == (snd_device_t)wsa_combo_devices[i]) {
+                char mixer_device_name[DEVICE_NAME_MAX_SIZE] = {0};
+                ALOGD("appending wsa extension to device %s",
+                        device_name);
+               strlcpy(mixer_device_name, WSA_MIXER_PATH_EXTENSION,
+                        sizeof(WSA_MIXER_PATH_EXTENSION)) ;
+                strlcat(mixer_device_name, device_name, DEVICE_NAME_MAX_SIZE);
+                strlcpy(device_name, mixer_device_name, DEVICE_NAME_MAX_SIZE-1);
+                break;
+            }
+        }
+    }
+
+
     if(snd_devices != NULL) {
         for (i = 0; i <  my_data->num_snd_devices; i++) {
             if (snd_device == (snd_device_t)snd_devices[i]) {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 378ca83..2f9c2e8 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1564,7 +1564,8 @@
 #define TZ_TYPE "/sys/class/thermal/thermal_zone%d/type"
 #define TZ_WSA "/sys/class/thermal/thermal_zone%d/temp"
 
-static bool is_wsa_found(int *wsaCount)
+static bool check_and_get_wsa_info(char *snd_card_name, int *wsaCount,
+                                   bool *is_wsa_combo_supported)
 {
     DIR *tdir = NULL;
     struct dirent *tdirent = NULL;
@@ -1614,6 +1615,18 @@
          ALOGD("Found %d WSA present on the platform", wsa_count);
          found = true;
          *wsaCount = wsa_count;
+
+        /* update wsa combo supported flag based on sound card name */
+        /* wsa combo flag needs to be set to true only for hardware
+           combinations which has support for both wsa and non-wsa speaker */
+        if (snd_card_name && (!strncmp(snd_card_name, "msm8953-snd-card-mtp",
+                sizeof("msm8953-snd-card-mtp"))) ||
+            !strncmp(snd_card_name, "msm8952-skum-snd-card",
+                sizeof("msm8952-skum-snd-card"))) {
+            *is_wsa_combo_supported = true;
+        } else {
+            *is_wsa_combo_supported = false;
+        }
     }
     closedir(tdir);
     chdir(cwd); /* Restore current working dir */
@@ -1634,6 +1647,7 @@
     struct mixer_ctl *ctl = NULL;
     int idx;
     int wsaCount =0;
+    bool is_wsa_combo_supported = false;
 
     my_data = calloc(1, sizeof(struct platform_data));
 
@@ -1749,14 +1763,19 @@
         }
     }
 
-    if (is_wsa_found(&wsaCount)) {
+    if (check_and_get_wsa_info(snd_card_name, &wsaCount, &is_wsa_combo_supported)) {
         /*Set ACDB ID of Stereo speaker if two WSAs are present*/
         /*Default ACDB ID for wsa speaker is that for mono*/
         if (wsaCount == 2) {
             platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_WSA, 15);
             platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_VBAT, 15);
         }
+
         my_data->is_wsa_speaker = true;
+
+        if (is_wsa_combo_supported)
+            hw_info_enable_wsa_combo_usecase_support(my_data->hw_info);
+
     }
 
     property_get("persist.audio.FFSP.enable", ffspEnable, "");