Merge "audio: Update pcm device ids for VI feedback and Voice2"
diff --git a/hal/Android.mk b/hal/Android.mk
index 6522bec..87ebeea 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -90,7 +90,7 @@
 endif
 
 ifneq ($(strip, $(AUDIO_FEATURE_DISABLED_SPKR_PROTECTION)),true)
-ifneq ($(filter msm8974,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8974 apq8084,$(TARGET_BOARD_PLATFORM)),)
     LOCAL_CFLAGS += -DSPKR_PROT_ENABLED
     LOCAL_SRC_FILES += audio_extn/spkr_protection.c
     LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index c480490..ed253c2 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -43,6 +43,7 @@
 #ifdef HFP_ENABLED
 #define AUDIO_PARAMETER_HFP_ENABLE      "hfp_enable"
 #define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
+#define AUDIO_PARAMETER_KEY_HFP_VOLUME "hfp_volume"
 
 static int32_t start_hfp(struct audio_device *adev,
                                struct str_parms *parms);
@@ -55,7 +56,7 @@
     struct pcm *hfp_pcm_rx;
     struct pcm *hfp_pcm_tx;
     bool is_hfp_running;
-    int hfp_volume;
+    float hfp_volume;
     audio_usecase_t ucid;
 };
 
@@ -79,6 +80,46 @@
     .avail_min = 0,
 };
 
+static int32_t hfp_set_volume(struct audio_device *adev, float value)
+{
+    int32_t vol, ret = 0;
+    struct mixer_ctl *ctl;
+    const char *mixer_ctl_name = "Internal HFP RX Volume";
+
+    ALOGV("%s: entry", __func__);
+    ALOGD("%s: (%f)\n", __func__, value);
+
+    if (value < 0.0) {
+        ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
+        value = 0.0;
+    } else {
+        value = ((value > 15.000000) ? 1.0 : (value / 15));
+        ALOGW("%s: Volume brought with in range (%f)\n", __func__, value);
+    }
+    vol  = lrint((value * 0x2000) + 0.5);
+    hfpmod.hfp_volume = value;
+
+    if (!hfpmod.is_hfp_running) {
+        ALOGV("%s: HFP not active, ignoring set_hfp_volume call", __func__);
+        return -EIO;
+    }
+
+    ALOGD("%s: Setting HFP volume to %d \n", __func__, vol);
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+              __func__, mixer_ctl_name);
+        return -EINVAL;
+    }
+    if(mixer_ctl_set_value(ctl, 0, vol) < 0) {
+        ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, vol);
+        return -EINVAL;
+    }
+
+    ALOGV("%s: exit", __func__);
+    return ret;
+}
+
 static int32_t start_hfp(struct audio_device *adev,
                                struct str_parms *parms)
 {
@@ -158,8 +199,8 @@
     pcm_start(hfpmod.hfp_pcm_rx);
     pcm_start(hfpmod.hfp_pcm_tx);
 
-
     hfpmod.is_hfp_running = true;
+    hfp_set_volume(adev, hfpmod.hfp_volume);
 
     ALOGD("%s: exit: status(%d)", __func__, ret);
     return 0;
@@ -238,6 +279,7 @@
     int ret;
     int rate;
     int val;
+    float vol;
     char value[32]={0};
 
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
@@ -275,5 +317,20 @@
                 select_devices(adev, hfpmod.ucid);
         }
     }
+
+    memset(value, 0, sizeof(value));
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_VOLUME,
+                            value, sizeof(value));
+    if (ret >= 0) {
+        if (sscanf(value, "%f", &vol) != 1){
+            ALOGE("%s: error in retrieving hfp volume", __func__);
+            ret = -EIO;
+            goto exit;
+        }
+        ALOGD("%s: set_hfp_volume usecase, Vol: [%f]", __func__, vol);
+        hfp_set_volume(adev, vol);
+    }
+exit:
+    ALOGV("%s Exit",__func__);
 }
 #endif /*HFP_ENABLED*/
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 4787ab3..9f76d31 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -296,6 +296,18 @@
         return 0;
     }
 
+    /* Set BT sample rate before enabling the devices. Adding sample rate mixer
+     * control in use-case does not work because rate update takes place after
+     * AFE port open due to the limitation of mixer control order execution.
+     */
+    if (snd_device == SND_DEVICE_OUT_BT_SCO) {
+        audio_route_apply_path(adev->audio_route, BT_SCO_SAMPLE_RATE);
+        audio_route_update_mixer(adev->audio_route);
+    } else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB) {
+        audio_route_apply_path(adev->audio_route, BT_SCO_WB_SAMPLE_RATE);
+        audio_route_update_mixer(adev->audio_route);
+    }
+
     /* start usb playback thread */
     if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
        SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
@@ -305,13 +317,14 @@
     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_VOICE_SPEAKER) &&
         audio_extn_spkr_prot_is_enabled()) {
-       if (audio_extn_spkr_prot_start_processing(snd_device)) {
-          ALOGE("%s: spkr_start_processing failed", __func__);
-          return -EINVAL;
-      }
-    }  else {
+        if (audio_extn_spkr_prot_start_processing(snd_device)) {
+            ALOGE("%s: spkr_start_processing failed", __func__);
+            return -EINVAL;
+        }
+    } else {
         ALOGV("%s: snd_device(%d: %s)", __func__,
         snd_device, device_name);
         if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
@@ -364,7 +377,8 @@
         if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
             audio_extn_usb_stop_capture(adev);
 
-        if (snd_device == SND_DEVICE_OUT_SPEAKER &&
+        if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
+            snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
             audio_extn_spkr_prot_is_enabled()) {
             audio_extn_spkr_prot_stop_processing();
         } else
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index e1172ef..7a79a1f 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -31,6 +31,9 @@
 #define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
 #define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
 
+#define BT_SCO_SAMPLE_RATE "bt-sco-samplerate"
+#define BT_SCO_WB_SAMPLE_RATE "bt-sco-wb-samplerate"
+
 /* Flags used to initialize acdb_settings variable that goes to ACDB library */
 #define NONE_FLAG            0x00000000
 #define DMIC_FLAG            0x00000002
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 0491d10..aa49c7b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -839,6 +839,13 @@
         strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
     else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
         strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
+    else if (snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
+             audio_extn_spkr_prot_is_enabled() ) {
+        char platform[PROPERTY_VALUE_MAX];
+        property_get("ro.board.platform", platform, "");
+        if (!strncmp("apq8084", platform, sizeof("apq8084")))
+            strlcat(mixer_path, " speaker-protected", MIXER_PATH_MAX_LENGTH);
+    }
 }
 
 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
@@ -997,21 +1004,28 @@
     int acdb_rx_id, acdb_tx_id;
     int ret = 0;
 
-    acdb_rx_id = acdb_device_table[out_snd_device];
+    if (my_data->csd == NULL)
+        return ret;
+
+    if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
+        audio_extn_spkr_prot_is_enabled())
+        acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+    else
+        acdb_rx_id = acdb_device_table[out_snd_device];
+
     acdb_tx_id = acdb_device_table[in_snd_device];
 
-    if (my_data->csd != NULL) {
-        if (acdb_rx_id > 0 && acdb_tx_id > 0) {
-            ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
-            if (ret < 0) {
-                ALOGE("%s: csd_enable_device_config, failed, error %d",
-                      __func__, ret);
-            }
-        } else {
-            ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
-                  acdb_rx_id, acdb_tx_id);
+    if (acdb_rx_id > 0 && acdb_tx_id > 0) {
+        ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
+        if (ret < 0) {
+            ALOGE("%s: csd_enable_device_config, failed, error %d",
+                  __func__, ret);
         }
+    } else {
+        ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
+              acdb_rx_id, acdb_tx_id);
     }
+
     return ret;
 }
 
@@ -1046,22 +1060,28 @@
     int acdb_rx_id, acdb_tx_id;
     int ret = 0;
 
-    acdb_rx_id = acdb_device_table[out_snd_device];
+    if (my_data->csd == NULL)
+        return ret;
+
+    if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
+        audio_extn_spkr_prot_is_enabled())
+        acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+    else
+        acdb_rx_id = acdb_device_table[out_snd_device];
+
     acdb_tx_id = acdb_device_table[in_snd_device];
 
-    if (my_data->csd != NULL) {
-        if (acdb_rx_id > 0 && acdb_tx_id > 0) {
-            ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id,
-                                              my_data->adev->acdb_settings);
-            if (ret < 0) {
-                ALOGE("%s: csd_enable_device, failed, error %d",
-                      __func__, ret);
-            }
-        } else {
-            ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
-                  acdb_rx_id, acdb_tx_id);
+    if (acdb_rx_id > 0 && acdb_tx_id > 0) {
+        ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id,
+                                          my_data->adev->acdb_settings);
+        if (ret < 0) {
+            ALOGE("%s: csd_enable_device, failed, error %d", __func__, ret);
         }
+    } else {
+        ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
+              acdb_rx_id, acdb_tx_id);
     }
+
     return ret;
 }
 
@@ -1747,11 +1767,6 @@
     if (err >= 0) {
         str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO);
         my_data->btsco_sample_rate = val;
-        if (val == SAMPLE_RATE_16KHZ) {
-            audio_route_apply_path(my_data->adev->audio_route,
-                                   "bt-sco-wb-samplerate");
-            audio_route_update_mixer(my_data->adev->audio_route);
-        }
     }
 
     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SLOWTALK, value, sizeof(value));
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 981ac93..1f25aa2 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -185,10 +185,8 @@
 #define INCALL_MUSIC_UPLINK2_PCM_DEVICE 14
 #elif PLATFORM_MSM8x26
 #define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
-#elif PLATFORM_MSM8974
-#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 35
 #else
-#define INCALL_MUSIC_UPLINK2_PCM_DEVICE -1
+#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 35
 #endif
 
 #define SPKR_PROT_CALIB_RX_PCM_DEVICE 5
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index 8a19038..657195d 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -160,12 +160,20 @@
         if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
             offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
             bass_ctxt->temp_disabled = true;
+            if (bass_ctxt->ctl)
+                offload_bassboost_send_params(bass_ctxt->ctl,
+                                              bass_ctxt->offload_bass,
+                                              OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
         }
     } else {
         if (!offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass)) &&
             bass_ctxt->temp_disabled) {
             offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
             bass_ctxt->temp_disabled = false;
+            if (bass_ctxt->ctl)
+                offload_bassboost_send_params(bass_ctxt->ctl,
+                                              bass_ctxt->offload_bass,
+                                              OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
         }
     }
     offload_bassboost_set_device(&(bass_ctxt->offload_bass), device);
@@ -214,7 +222,9 @@
     bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
 
     ALOGV("%s", __func__);
-    if (!offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
+
+    if (!offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass)) &&
+        !(bass_ctxt->temp_disabled)) {
         offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
         if (bass_ctxt->ctl && bass_ctxt->strength)
             offload_bassboost_send_params(bass_ctxt->ctl,
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index d2957e9..54bca07 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -160,12 +160,20 @@
         if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {
             offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false);
             virt_ctxt->temp_disabled = true;
+            if (virt_ctxt->ctl)
+                offload_virtualizer_send_params(virt_ctxt->ctl,
+                                              virt_ctxt->offload_virt,
+                                              OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
         }
     } else {
         if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)) &&
             virt_ctxt->temp_disabled) {
             offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
             virt_ctxt->temp_disabled = false;
+            if (virt_ctxt->ctl)
+                offload_virtualizer_send_params(virt_ctxt->ctl,
+                                              virt_ctxt->offload_virt,
+                                              OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
         }
     }
     offload_virtualizer_set_device(&(virt_ctxt->offload_virt), device);
@@ -213,7 +221,9 @@
     virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context;
 
     ALOGV("%s", __func__);
-    if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {
+
+    if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)) &&
+        !(virt_ctxt->temp_disabled)) {
         offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
         if (virt_ctxt->ctl && virt_ctxt->strength)
             offload_virtualizer_send_params(virt_ctxt->ctl,