audio: unify hal

Unify audio hal components

CRs-Fixed: 2380934
Change-Id: Iacafdc44d935de5f343240421a1572a0a3241bd0
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index 89c42c8..3eb96d6 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -31,7 +31,7 @@
 
 #include <errno.h>
 #include <math.h>
-#include <cutils/log.h>
+#include <log/log.h>
 
 #include "audio_hw.h"
 #include "platform.h"
@@ -52,9 +52,13 @@
 #define AUDIO_PARAMETER_KEY_HFP_VOLUME "hfp_volume"
 #define AUDIO_PARAMETER_HFP_PCM_DEV_ID "hfp_pcm_dev_id"
 
+#define AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME "hfp_mic_volume"
+#define PLAYBACK_VOLUME_MAX 0x2000
+#define CAPTURE_VOLUME_DEFAULT                (15.0)
+
 #ifdef PLATFORM_MSM8994
 #define HFP_RX_VOLUME     "SEC AUXPCM LOOPBACK Volume"
-#elif defined PLATFORM_MSM8996
+#elif defined (PLATFORM_MSM8996) || defined (EXTERNAL_BT_SUPPORTED)
 #define HFP_RX_VOLUME     "PRI AUXPCM LOOPBACK Volume"
 #elif defined PLATFORM_AUTO
 #define HFP_RX_VOLUME     "Playback 36 Volume"
@@ -78,6 +82,8 @@
     float hfp_volume;
     int32_t hfp_pcm_dev_id;
     audio_usecase_t ucid;
+    float mic_volume;
+    bool mic_mute;
 };
 
 static struct hfp_module hfpmod = {
@@ -89,7 +95,10 @@
     .hfp_volume = 0,
     .hfp_pcm_dev_id = HFP_ASM_RX_TX,
     .ucid = USECASE_AUDIO_HFP_SCO,
+    .mic_volume = CAPTURE_VOLUME_DEFAULT,
+    .mic_mute = 0,
 };
+
 static struct pcm_config pcm_config_hfp = {
     .channels = 1,
     .rate = 8000,
@@ -111,6 +120,7 @@
     ALOGD("%s: (%f)\n", __func__, value);
 
     hfpmod.hfp_volume = value;
+
     if (value < 0.0) {
         ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
         value = 0.0;
@@ -141,6 +151,114 @@
     return ret;
 }
 
+/*Set mic volume to value.
+*
+* This interface is used for mic volume control, set mic volume as value(range 0 ~ 15).
+*/
+static int hfp_set_mic_volume(struct audio_device *adev, float value)
+{
+    int volume, ret = 0;
+    char mixer_ctl_name[128];
+    struct mixer_ctl *ctl;
+    int pcm_device_id = HFP_ASM_RX_TX;
+
+    if (!hfpmod.is_hfp_running) {
+        ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
+        return -EIO;
+    }
+
+    if (value < 0.0) {
+        ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
+        value = 0.0;
+    } else if (value > CAPTURE_VOLUME_DEFAULT) {
+        value = CAPTURE_VOLUME_DEFAULT;
+        ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
+    }
+
+    value = value / CAPTURE_VOLUME_DEFAULT;
+    memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+             "Playback %d Volume", pcm_device_id);
+    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;
+    }
+    volume = (int)(value * PLAYBACK_VOLUME_MAX);
+
+    ALOGD("%s: Setting volume to %d (%s)\n", __func__, volume, mixer_ctl_name);
+    if (mixer_ctl_set_value(ctl, 0, volume) < 0) {
+        ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
+        return -EINVAL;
+    }
+
+    return ret;
+}
+
+static float hfp_get_mic_volume(struct audio_device *adev)
+{
+    int volume;
+    char mixer_ctl_name[128];
+    struct mixer_ctl *ctl;
+    int pcm_device_id = HFP_ASM_RX_TX;
+    float value = 0.0;
+
+    if (!hfpmod.is_hfp_running) {
+        ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
+        return -EIO;
+    }
+
+    memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+             "Playback %d Volume", pcm_device_id);
+    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;
+    }
+
+    volume = mixer_ctl_get_value(ctl, 0);
+    if ( volume < 0) {
+        ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
+        return -EINVAL;
+    }
+    ALOGD("%s: getting mic volume %d \n", __func__, volume);
+
+    value = (volume / PLAYBACK_VOLUME_MAX) * CAPTURE_VOLUME_DEFAULT;
+    if (value < 0.0) {
+        ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
+        value = 0.0;
+    } else if (value > CAPTURE_VOLUME_DEFAULT) {
+        value = CAPTURE_VOLUME_DEFAULT;
+        ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
+    }
+
+    return value;
+}
+
+/*Set mic mute state.
+*
+* This interface is used for mic mute state control
+*/
+int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state)
+{
+    int rc = 0;
+
+    if (state == hfpmod.mic_mute)
+        return rc;
+
+    if (state == true) {
+        hfpmod.mic_volume = hfp_get_mic_volume(adev);
+    }
+    rc = hfp_set_mic_volume(adev, (state == true) ? 0.0 : hfpmod.mic_volume);
+    adev->voice.mic_mute = state;
+    hfpmod.mic_mute = state;
+    ALOGD("%s: Setting mute state %d, rc %d\n", __func__, state, rc);
+    return rc;
+}
+
 static int32_t start_hfp(struct audio_device *adev,
                          struct str_parms *parms __unused)
 {
@@ -150,6 +268,13 @@
 
     ALOGD("%s: enter", __func__);
 
+    if (adev->enable_hfp == true) {
+        ALOGD("%s: HFP is already active!\n", __func__);
+        return 0;
+    }
+    adev->enable_hfp = true;
+    platform_set_mic_mute(adev->platform, false);
+
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
 
     if (!uc_info)
@@ -197,8 +322,8 @@
     }
 
     hfpmod.hfp_pcm_rx = pcm_open(adev->snd_card,
-                                   pcm_dev_rx_id,
-                                   PCM_OUT, &pcm_config_hfp);
+                                 pcm_dev_rx_id,
+                                 PCM_OUT, &pcm_config_hfp);
     if (hfpmod.hfp_pcm_rx && !pcm_is_ready(hfpmod.hfp_pcm_rx)) {
         ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_rx));
         ret = -EIO;
@@ -215,8 +340,8 @@
     }
 
     hfpmod.hfp_pcm_tx = pcm_open(adev->snd_card,
-                                   pcm_dev_tx_id,
-                                   PCM_IN, &pcm_config_hfp);
+                                 pcm_dev_tx_id,
+                                 PCM_IN, &pcm_config_hfp);
     if (hfpmod.hfp_pcm_tx && !pcm_is_ready(hfpmod.hfp_pcm_tx)) {
         ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_tx));
         ret = -EIO;
@@ -233,6 +358,7 @@
         ret = -EINVAL;
         goto exit;
     }
+
     if (pcm_start(hfpmod.hfp_pcm_rx) < 0) {
         ALOGE("%s: pcm start for hfp pcm rx failed", __func__);
         ret = -EINVAL;
@@ -247,6 +373,10 @@
     hfpmod.is_hfp_running = true;
     hfp_set_volume(adev, hfpmod.hfp_volume);
 
+    /* Set mic volume by mute status, we don't provide set mic volume in phone app, only
+    provide mute and unmute. */
+    audio_extn_hfp_set_mic_mute(adev, adev->mic_muted);
+
     ALOGD("%s: exit: status(%d)", __func__, ret);
     return 0;
 
@@ -305,6 +435,13 @@
     disable_snd_device(adev, uc_info->out_snd_device);
     disable_snd_device(adev, uc_info->in_snd_device);
 
+    /* Set the unmute Tx mixer control */
+    if (voice_get_mic_mute(adev)) {
+        platform_set_mic_mute(adev->platform, false);
+        ALOGD("%s: unMute HFP Tx", __func__);
+    }
+    adev->enable_hfp = false;
+
     list_remove(&uc_info->list);
     free(uc_info);
 
@@ -413,6 +550,19 @@
         str_parms_del(parms, AUDIO_PARAMETER_HFP_PCM_DEV_ID);
     }
 
+    memset(value, 0, sizeof(value));
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME,
+                            value, sizeof(value));
+    if (ret >= 0) {
+        if (sscanf(value, "%f", &vol) != 1){
+            ALOGE("%s: error in retrieving hfp mic volume", __func__);
+            ret = -EIO;
+            goto exit;
+        }
+        ALOGD("%s: set_hfp_mic_volume usecase, Vol: [%f]", __func__, vol);
+        hfp_set_mic_volume(adev, vol);
+    }
+
 exit:
     ALOGV("%s Exit",__func__);
 }