summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvivek mehta <mvivek@codeaurora.org>2015-08-07 19:46:06 -0700
committerEric Laurent <elaurent@google.com>2015-08-20 13:02:07 -0700
commit765eb645d3a83949a05eecb9f22a84bd47978c19 (patch)
tree503be88d17a95f59b1bef8a31b0c001301a01be5
parent65ad12de29cc94d65b2efc76588ae69ba941ba98 (diff)
downloadhardware_qcom_audio-765eb645d3a83949a05eecb9f22a84bd47978c19.tar.gz
hardware_qcom_audio-765eb645d3a83949a05eecb9f22a84bd47978c19.tar.bz2
hardware_qcom_audio-765eb645d3a83949a05eecb9f22a84bd47978c19.zip
hal: Fix sidetone sequence during voice call
When sidetone is enabled during voice call, the RX and TX path mixer controls are issued back to back, this causes the codec path to be enabled from TX to RX as the internal loopback for sidetone exists. Due to enabling this path, pop noise is observed on headphones. This issue is fixed by treating sidetone as special case and changing the enable and disable sequence of sidetone mixer controls. Based on CAF commit : I7aea55af963cf939286e5b349ff25fd783314679 BUG=23135950 Change-Id: Ib5759e08d9b5948a76545b032d882231410cfa2a
-rw-r--r--hal/audio_hw.c9
-rw-r--r--hal/msm8974/platform.h1
-rw-r--r--hal/voice.c98
-rw-r--r--hal/voice.h5
4 files changed, 94 insertions, 19 deletions
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7c017fd3..b307f6c4 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -683,6 +683,9 @@ int select_devices(struct audio_device *adev,
(usecase->in_snd_device != SND_DEVICE_NONE) &&
(usecase->out_snd_device != SND_DEVICE_NONE)) {
status = platform_switch_voice_call_device_pre(adev->platform);
+ /* Disable sidetone only if voice call already exists */
+ if (voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, usecase->out_snd_device, false);
}
/* Disable current sound devices */
@@ -734,10 +737,14 @@ int select_devices(struct audio_device *adev,
* Enable device command should be sent to modem only after
* enabling voice call mixer controls
*/
- if (usecase->type == VOICE_CALL)
+ if (usecase->type == VOICE_CALL) {
status = platform_switch_voice_call_usecase_route_post(adev->platform,
out_snd_device,
in_snd_device);
+ /* Enable sidetone only if voice call already exists */
+ if (voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, out_snd_device, true);
+ }
return status;
}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index b166e2fe..1c067267 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -148,6 +148,7 @@ enum {
#define ALL_SESSION_VSID 0xFFFFFFFF
#define DEFAULT_MUTE_RAMP_DURATION_MS 20
#define DEFAULT_VOLUME_RAMP_DURATION_MS 20
+#define MIXER_PATH_MAX_LENGTH 100
#define ACDB_ID_VOICE_SPEAKER 15
#define ACDB_ID_VOICE_HANDSET 7
diff --git a/hal/voice.c b/hal/voice.c
index 1f36b36b..a33305d3 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -52,6 +52,58 @@ static struct voice_session *voice_get_session_from_use_case(struct audio_device
return session;
}
+static bool voice_is_sidetone_device(snd_device_t out_device,
+ char *mixer_path)
+{
+ bool is_sidetone_dev = true;
+
+ switch (out_device) {
+ case SND_DEVICE_OUT_VOICE_HAC_HANDSET:
+ strlcpy(mixer_path, "sidetone-hac-handset", MIXER_PATH_MAX_LENGTH);
+ break;
+ case SND_DEVICE_OUT_VOICE_HANDSET:
+ strlcpy(mixer_path, "sidetone-handset", MIXER_PATH_MAX_LENGTH);
+ break;
+ case SND_DEVICE_OUT_VOICE_HEADPHONES:
+ strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH);
+ break;
+ default:
+ is_sidetone_dev = false;
+ break;
+ }
+
+ return is_sidetone_dev;
+}
+
+void voice_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device, bool enable)
+{
+ char mixer_path[MIXER_PATH_MAX_LENGTH];
+ bool is_sidetone_dev;
+
+ ALOGD("%s: %s, out_snd_device: %d\n",
+ __func__, (enable ? "enable" : "disable"),
+ out_snd_device);
+
+ is_sidetone_dev = voice_is_sidetone_device(out_snd_device, mixer_path);
+
+ if (!is_sidetone_dev) {
+ ALOGD("%s: device %d does not support sidetone\n",
+ __func__, out_snd_device);
+ return;
+ }
+
+ ALOGD("%s: sidetone out device = %s\n",
+ __func__, mixer_path);
+
+ if (enable)
+ audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+ else
+ audio_route_reset_and_update_path(adev->audio_route, mixer_path);
+
+ return;
+}
+
int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
{
int i, ret = 0;
@@ -61,8 +113,20 @@ int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);
session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
+
+ uc_info = get_usecase_from_list(adev, usecase_id);
+ if (uc_info == NULL) {
+ ALOGE("%s: Could not find the usecase (%d) in the list",
+ __func__, usecase_id);
+ return -EINVAL;
+ }
+
session->state.current = CALL_INACTIVE;
+ /* Disable sidetone only when no calls are active */
+ if (!voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, uc_info->out_snd_device, false);
+
ret = platform_stop_voice_call(adev->platform, session->vsid);
/* 1. Close the PCM devices */
@@ -75,13 +139,6 @@ int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
session->pcm_tx = NULL;
}
- uc_info = get_usecase_from_list(adev, usecase_id);
- if (uc_info == NULL) {
- ALOGE("%s: Could not find the usecase (%d) in the list",
- __func__, usecase_id);
- return -EINVAL;
- }
-
/* 2. Get and set stream specific mixer controls */
disable_audio_route(adev, uc_info);
@@ -129,6 +186,17 @@ int voice_start_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
goto error_start_voice;
}
+ ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ session->pcm_tx = pcm_open(adev->snd_card,
+ pcm_dev_tx_id,
+ PCM_IN, &voice_config);
+ if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
+ ret = -EIO;
+ goto error_start_voice;
+ }
+
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
__func__, adev->snd_card, pcm_dev_rx_id);
session->pcm_rx = pcm_open(adev->snd_card,
@@ -140,18 +208,12 @@ int voice_start_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
goto error_start_voice;
}
- ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, adev->snd_card, pcm_dev_tx_id);
- session->pcm_tx = pcm_open(adev->snd_card,
- pcm_dev_tx_id,
- PCM_IN, &voice_config);
- if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
- ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
- ret = -EIO;
- goto error_start_voice;
- }
- pcm_start(session->pcm_rx);
pcm_start(session->pcm_tx);
+ pcm_start(session->pcm_rx);
+
+ /* Enable sidetone only when no calls are already active */
+ if (!voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, uc_info->out_snd_device, true);
voice_set_volume(adev, adev->voice.volume);
diff --git a/hal/voice.h b/hal/voice.h
index 76f9d0dd..23b9ee39 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -40,6 +40,7 @@ struct str_parms;
struct stream_in;
struct stream_out;
typedef int audio_usecase_t;
+typedef int snd_device_t;
struct call_state {
int current;
@@ -90,4 +91,8 @@ int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev,
struct stream_in *in);
void voice_update_devices_for_all_voice_usecases(struct audio_device *adev);
+void voice_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device,
+ bool enable);
+bool voice_is_call_state_active(struct audio_device *adev);
#endif //VOICE_H