diff options
author | Vignesh Kulothungan <vigneshk@quicinc.com> | 2018-01-23 11:25:18 -0800 |
---|---|---|
committer | Carter Hsu <carterhsu@google.com> | 2018-12-17 19:19:57 +0800 |
commit | 6469882bc7e9064ffd1fcd16a44f67e93381c801 (patch) | |
tree | b001cd554e237e6313fc7d7f1294912c456b53a3 /hal/audio_hw.c | |
parent | 222f4bf271388e9c266e89d304a32d866a053997 (diff) | |
download | android_hardware_qcom_audio-6469882bc7e9064ffd1fcd16a44f67e93381c801.tar.gz android_hardware_qcom_audio-6469882bc7e9064ffd1fcd16a44f67e93381c801.tar.bz2 android_hardware_qcom_audio-6469882bc7e9064ffd1fcd16a44f67e93381c801.zip |
hal: Add dynamic enablement of AEC/NS for VoIP
Add capability to dynamically enable or disable AEC/NS audio effects
on DSP for a VoIP call.
Bug: 70805651
Test: manual
Change-Id: I16f1f6664b39afaedfca92afbc87002685f6e369
Diffstat (limited to 'hal/audio_hw.c')
-rw-r--r-- | hal/audio_hw.c | 159 |
1 files changed, 156 insertions, 3 deletions
diff --git a/hal/audio_hw.c b/hal/audio_hw.c index 5af3897f..e1d53094 100644 --- a/hal/audio_hw.c +++ b/hal/audio_hw.c @@ -807,6 +807,147 @@ int disable_snd_device(struct audio_device *adev, return 0; } +#ifdef DYNAMIC_ECNS_ENABLED +static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev, + struct stream_in *in, + struct audio_effect_config effect_config, + unsigned int param_value) +{ + char mixer_ctl_name[] = "Audio Effect"; + long set_values[6]; + + struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); + if (!ctl) { + ALOGE("%s: Could not get mixer ctl - %s", + __func__, mixer_ctl_name); + return -EINVAL; + } + + set_values[0] = 1; //0:Rx 1:Tx + set_values[1] = in->app_type_cfg.app_type; + set_values[2] = (long)effect_config.module_id; + set_values[3] = (long)effect_config.instance_id; + set_values[4] = (long)effect_config.param_id; + set_values[5] = param_value; + + mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); + + return 0; + +} + +static int update_effect_param_ecns(struct audio_usecase *usecase, + unsigned int module_id, int effect_type, + unsigned int *param_value) +{ + int ret = 0; + struct audio_effect_config other_effect_config; + struct stream_in *in = NULL; + + if (!usecase) + return -EINVAL; + + in = usecase->stream.in; + + /* Get the effect config data of the other effect */ + ret = platform_get_effect_config_data(usecase->in_snd_device, + &other_effect_config, + effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC); + if (ret < 0) { + ALOGE("%s Failed to get effect params %d", __func__, ret); + return ret; + } + + if (module_id == other_effect_config.module_id) { + //Same module id for AEC/NS. Values need to be combined + if (((effect_type == EFFECT_AEC) && (in->enable_ns)) || + ((effect_type == EFFECT_NS) && (in->enable_aec))) + *param_value |= other_effect_config.param_value; + } + + return ret; +} + +static int enable_disable_effect(struct audio_device *adev, struct stream_in *in, + int effect_type, bool enable) +{ + struct audio_effect_config effect_config; + struct audio_usecase *usecase = NULL; + int ret = 0; + unsigned int param_value = 0; + + if (!in) { + ALOGE("%s: Invalid input stream", __func__); + return -EINVAL; + } + + ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable); + + usecase = get_usecase_from_list(adev, in->usecase); + + ret = platform_get_effect_config_data(usecase->in_snd_device, + &effect_config, effect_type); + if (ret < 0) { + ALOGE("%s Failed to get module id %d", __func__, ret); + return ret; + } + ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d", + __func__, effect_config.module_id, in->app_type_cfg.app_type, + usecase->id, usecase->in_snd_device); + + if (enable) + param_value = effect_config.param_value; + + /*Special handling for AEC & NS effects Param values need to be + updated if module ids are same*/ + + if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) { + ret = update_effect_param_ecns(usecase, effect_config.module_id, + effect_type, ¶m_value); + if (ret < 0) + return ret; + } + + ret = send_effect_enable_disable_mixer_ctl(adev, in, + effect_config, param_value); + + return ret; +} + +static int check_and_enable_effect(struct audio_device *adev) +{ + int ret = 0; + + struct listnode *node; + struct stream_in *in = NULL; + + list_for_each(node, &adev->usecase_list) + { + struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list); + if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) { + in = usecase->stream.in; + + if (in->standby) + continue; + + if (in->enable_aec) { + ret = enable_disable_effect(adev, in, EFFECT_AEC, true); + } + + if (in->enable_ns && + in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) { + ret = enable_disable_effect(adev, in, EFFECT_NS, true); + } + } + } + + return ret; +} +#else +#define enable_disable_effect(w, x, y, z) -ENOSYS +#define check_and_enable_effect(x) -ENOSYS +#endif + /* legend: uc - existing usecase @@ -1543,6 +1684,11 @@ int select_devices(struct audio_device *adev, audio_extn_ma_set_device(usecase); + /* If input stream is already running the effect needs to be + applied on the new input device that's being enabled here. */ + if (in_snd_device != SND_DEVICE_NONE) + check_and_enable_effect(adev); + /* Applicable only on the targets that has external modem. * Enable device command should be sent to modem only after * enabling voice call mixer controls @@ -1708,6 +1854,7 @@ int start_input_stream(struct stream_in *in) } } register_in_stream(in); + check_and_enable_effect(adev); audio_streaming_hint_end(); audio_extn_perf_lock_release(); ALOGV("%s: exit", __func__); @@ -3954,6 +4101,8 @@ static int add_remove_audio_effect(const struct audio_stream *stream, effect_descriptor_t desc; status = (*effect)->get_descriptor(effect, &desc); + ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable); + if (status != 0) return status; @@ -3978,14 +4127,18 @@ static int add_remove_audio_effect(const struct audio_stream *stream, select_devices(adev, usecase->id); } } - if (!in->standby) + if (!in->standby + && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS) select_devices(in->dev, in->usecase); } if (in->enable_ns != enable && (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) { in->enable_ns = enable; - if (!in->standby) - select_devices(in->dev, in->usecase); + if (!in->standby) { + if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION + || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS) + select_devices(in->dev, in->usecase); + } } pthread_mutex_unlock(&in->dev->lock); pthread_mutex_unlock(&in->lock); |