diff options
author | Uday Kishore Pasupuleti <upasupul@codeaurora.org> | 2016-01-06 19:12:41 -0800 |
---|---|---|
committer | Prashant Malani <pmalani@google.com> | 2016-01-08 17:00:16 -0800 |
commit | 582e0a5e965897ea54ecfa5fe206797dab577a45 (patch) | |
tree | 3d99bdf637b54008f1e906975d75f7de7bfb6fb6 /msm8909/post_proc/virtualizer.c | |
parent | befe610a877c3b150a6dd90cf358df4945b8f9a6 (diff) | |
download | hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.tar.gz hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.tar.bz2 hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.zip |
audio: msm8909w caf release LW.BR.1.0-00410-8x09w.0
MSM8909w Audio HAL code copied from CAF release
LW.BR.1.0-00410-8x09w.0
dbcce50 hal: Port wcd9326 changes to 8909
410c530 hal: update error handling for pcm_prepare failures
ff79309 hal: fix compilation issues with audio FM extention
762d7eb policy_hal: add support for fm device loopback
7c418f9 audio_policy: modify few methods to appropriately override base
8b12163 audio: Add support to enable split A2DP
a0559fa Revert "Revert "policy_hal: Function prototype correction for custom policy"."
Fixed makefiles to be compatible with PDK without kernel source
Change-Id: I9c6f2139adee62426b877516deeb41d4ed8052b2
Diffstat (limited to 'msm8909/post_proc/virtualizer.c')
-rw-r--r-- | msm8909/post_proc/virtualizer.c | 503 |
1 files changed, 503 insertions, 0 deletions
diff --git a/msm8909/post_proc/virtualizer.c b/msm8909/post_proc/virtualizer.c new file mode 100644 index 00000000..dcddfe70 --- /dev/null +++ b/msm8909/post_proc/virtualizer.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "offload_effect_virtualizer" +#define LOG_NDEBUG 0 + +#include <cutils/list.h> +#include <cutils/log.h> +#include <tinyalsa/asoundlib.h> +#include <sound/audio_effects.h> +#include <audio_effects/effect_virtualizer.h> + +#include "effect_api.h" +#include "virtualizer.h" + +/* Offload Virtualizer UUID: 509a4498-561a-4bea-b3b1-0002a5d5c51b */ +const effect_descriptor_t virtualizer_descriptor = { + {0x37cc2c00, 0xdddd, 0x11db, 0x8577, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + {0x509a4498, 0x561a, 0x4bea, 0xb3b1, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid + EFFECT_CONTROL_API_VERSION, + (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_DEVICE_IND | EFFECT_FLAG_HW_ACC_TUNNEL), + 0, /* TODO */ + 1, + "MSM offload virtualizer", + "The Android Open Source Project", +}; + +/* + * Virtualizer operations + */ + +int virtualizer_get_strength(virtualizer_context_t *context) +{ + ALOGV("%s: ctxt %p, strength: %d", __func__, context, context->strength); + return context->strength; +} + +int virtualizer_set_strength(virtualizer_context_t *context, uint32_t strength) +{ + ALOGV("%s: ctxt %p, strength: %d", __func__, context, strength); + context->strength = strength; + + offload_virtualizer_set_strength(&(context->offload_virt), strength); + if (context->ctl) + offload_virtualizer_send_params(context->ctl, context->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG | + OFFLOAD_SEND_VIRTUALIZER_STRENGTH); + return 0; +} + +/* + * Check if an audio device is supported by this implementation + * + * [in] + * device device that is intented for processing (e.g. for binaural vs transaural) + * [out] + * false device is not applicable for effect + * true device is applicable for effect + */ +bool virtualizer_is_device_supported(audio_devices_t device) { + switch (device) { + case AUDIO_DEVICE_OUT_SPEAKER: + case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: +#ifdef AFE_PROXY_ENABLED + case AUDIO_DEVICE_OUT_PROXY: +#endif + case AUDIO_DEVICE_OUT_AUX_DIGITAL: + case AUDIO_DEVICE_OUT_USB_ACCESSORY: + case AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET: + return false; + default : + return true; + } +} + +/* + * Check if a channel mask + audio device is supported by this implementation + * + * [in] + * channel_mask channel mask of input buffer + * device device that is intented for processing (e.g. for binaural vs transaural) + * [out] + * false if the configuration is not supported or it is unknown + * true if the configuration is supported + */ +bool virtualizer_is_configuration_supported(audio_channel_mask_t channel_mask, + audio_devices_t device) { + uint32_t channelCount = audio_channel_count_from_out_mask(channel_mask); + if ((channelCount == 0) || (channelCount > 2)) { + return false; + } + + return virtualizer_is_device_supported(device); +} + +/* + * Force the virtualization mode to that of the given audio device + * + * [in] + * context effect engine context + * forced_device device whose virtualization mode we'll always use + * [out] + * -EINVAL if the device is not supported or is unknown + * 0 if the device is supported and the virtualization mode forced + */ +int virtualizer_force_virtualization_mode(virtualizer_context_t *context, + audio_devices_t forced_device) { + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + int status = 0; + bool use_virt = false; + int is_virt_enabled = + offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)); + + ALOGV("%s: ctxt %p, forcedDev=0x%x enabled=%d tmpDisabled=%d", __func__, virt_ctxt, + forced_device, is_virt_enabled, virt_ctxt->temp_disabled); + + if (virtualizer_is_device_supported(forced_device) == false) { + if (forced_device != AUDIO_DEVICE_NONE) { + //forced device is not supported, make it behave as a reset of forced mode + forced_device = AUDIO_DEVICE_NONE; + // but return an error + status = -EINVAL; + } + } + + if (forced_device == AUDIO_DEVICE_NONE) { + // disabling forced virtualization mode: + // verify whether the virtualization should be enabled or disabled + if (virtualizer_is_device_supported(virt_ctxt->device)) { + use_virt = (is_virt_enabled == true); + } + virt_ctxt->forced_device = AUDIO_DEVICE_NONE; + } else { + // forcing virtualization mode: + // TODO: we assume device is supported, so hard coded a fixed one. + virt_ctxt->forced_device = AUDIO_DEVICE_OUT_WIRED_HEADPHONE; + // TODO: only enable for a supported mode, when the effect is enabled + use_virt = (is_virt_enabled == true); + } + + if (use_virt) { + if (virt_ctxt->temp_disabled == true) { + if (effect_is_active(&virt_ctxt->common)) { + offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true); + if (virt_ctxt->ctl) + offload_virtualizer_send_params(virt_ctxt->ctl, + virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); + } + ALOGV("%s: re-enable VIRTUALIZER", __func__); + virt_ctxt->temp_disabled = false; + } else { + ALOGV("%s: leaving VIRTUALIZER enabled", __func__); + } + } else { + if (virt_ctxt->temp_disabled == false) { + if (effect_is_active(&virt_ctxt->common)) { + offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false); + if (virt_ctxt->ctl) + offload_virtualizer_send_params(virt_ctxt->ctl, + virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); + } + ALOGV("%s: disable VIRTUALIZER", __func__); + virt_ctxt->temp_disabled = true; + } else { + ALOGV("%s: leaving VIRTUALIZER disabled", __func__); + } + } + + ALOGV("after %s: ctxt %p, enabled=%d tmpDisabled=%d", __func__, virt_ctxt, + is_virt_enabled, virt_ctxt->temp_disabled); + + return status; +} + +/* + * Get the virtual speaker angles for a channel mask + audio device configuration + * which is guaranteed to be supported by this implementation + * + * [in] + * channel_mask the channel mask of the input to virtualize + * device the type of device that affects the processing (e.g. for binaural vs transaural) + * [in/out] + * speaker_angles the array of integer where each speaker angle is written as a triplet in the + * following format: + * int32_t a bit mask with a single value selected for each speaker, following + * the convention of the audio_channel_mask_t type + * int32_t a value in degrees expressing the speaker azimuth, where 0 is in front + * of the user, 180 behind, -90 to the left, 90 to the right of the user + * int32_t a value in degrees expressing the speaker elevation, where 0 is the + * horizontal plane, +90 is directly above the user, -90 below + * + */ +void virtualizer_get_speaker_angles(audio_channel_mask_t channel_mask __unused, + audio_devices_t device __unused, int32_t *speaker_angles) { + // the channel count is guaranteed to be 1 or 2 + // the device is guaranteed to be of type headphone + // this virtualizer is always 2in with speakers at -90 and 90deg of azimuth, 0deg of elevation + *speaker_angles++ = (int32_t) AUDIO_CHANNEL_OUT_FRONT_LEFT; + *speaker_angles++ = -90; // azimuth + *speaker_angles++ = 0; // elevation + *speaker_angles++ = (int32_t) AUDIO_CHANNEL_OUT_FRONT_RIGHT; + *speaker_angles++ = 90; // azimuth + *speaker_angles = 0; // elevation +} + +/* + * Retrieve the current device whose processing mode is used by this effect + * + * [out] + * AUDIO_DEVICE_NONE if the effect is not virtualizing + * or the device type if the effect is virtualizing + */ +audio_devices_t virtualizer_get_virtualization_mode(virtualizer_context_t *context) { + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + audio_devices_t device = AUDIO_DEVICE_NONE; + + if ((offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) + && (virt_ctxt->temp_disabled == false)) { + if (virt_ctxt->forced_device != AUDIO_DEVICE_NONE) { + // virtualization mode is forced, return that device + device = virt_ctxt->forced_device; + } else { + // no forced mode, return the current device + device = virt_ctxt->device; + } + } + ALOGV("%s: returning 0x%x", __func__, device); + return device; +} + +int virtualizer_get_parameter(effect_context_t *context, effect_param_t *p, + uint32_t *size) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); + int32_t *param_tmp = (int32_t *)p->data; + int32_t param = *param_tmp++; + void *value = p->data + voffset; + int i; + + ALOGV("%s: ctxt %p, param %d", __func__, virt_ctxt, param); + + p->status = 0; + + switch (param) { + case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: + if (p->vsize < sizeof(uint32_t)) + p->status = -EINVAL; + p->vsize = sizeof(uint32_t); + break; + case VIRTUALIZER_PARAM_STRENGTH: + if (p->vsize < sizeof(int16_t)) + p->status = -EINVAL; + p->vsize = sizeof(int16_t); + break; + case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: + // return value size can only be interpreted as relative to input value, + // deferring validity check to below + break; + case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: + if (p->vsize != sizeof(uint32_t)) + p->status = -EINVAL; + p->vsize = sizeof(uint32_t); + break; + default: + p->status = -EINVAL; + } + + *size = sizeof(effect_param_t) + voffset + p->vsize; + + if (p->status != 0) + return 0; + + switch (param) { + case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: + *(uint32_t *)value = 1; + break; + + case VIRTUALIZER_PARAM_STRENGTH: + *(int16_t *)value = virtualizer_get_strength(virt_ctxt); + break; + + case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: + { + const audio_channel_mask_t channel_mask = (audio_channel_mask_t) *param_tmp++; + const audio_devices_t device = (audio_devices_t) *param_tmp; + uint32_t channel_cnt = audio_channel_count_from_out_mask(channel_mask); + + if (p->vsize < 3 * channel_cnt * sizeof(int32_t)){ + p->status = -EINVAL; + break; + } + // verify the configuration is supported + if(virtualizer_is_configuration_supported(channel_mask, device)) { + // configuration is supported, get the angles + virtualizer_get_speaker_angles(channel_mask, device, (int32_t *)value); + } else { + p->status = -EINVAL; + } + + break; + } + + case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: + *(uint32_t *)value = (uint32_t) virtualizer_get_virtualization_mode(virt_ctxt); + break; + + default: + p->status = -EINVAL; + break; + } + + return 0; +} + +int virtualizer_set_parameter(effect_context_t *context, effect_param_t *p, + uint32_t size __unused) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); + void *value = p->data + voffset; + int32_t *param_tmp = (int32_t *)p->data; + int32_t param = *param_tmp++; + uint32_t strength; + + ALOGV("%s: ctxt %p, param %d", __func__, virt_ctxt, param); + + p->status = 0; + + switch (param) { + case VIRTUALIZER_PARAM_STRENGTH: + strength = (uint32_t)(*(int16_t *)value); + virtualizer_set_strength(virt_ctxt, strength); + break; + case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: + { + const audio_devices_t device = *(audio_devices_t *)value; + if (0 != virtualizer_force_virtualization_mode(virt_ctxt, device)) { + p->status = -EINVAL; + } + break; + } + default: + p->status = -EINVAL; + break; + } + + return 0; +} + +int virtualizer_set_device(effect_context_t *context, uint32_t device) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + ALOGV("%s: ctxt %p, device: 0x%x", __func__, virt_ctxt, device); + virt_ctxt->device = device; + + if (virt_ctxt->forced_device == AUDIO_DEVICE_NONE) { + // default case unless configuration is forced + if (virtualizer_is_device_supported(device) == false) { + if (!virt_ctxt->temp_disabled) { + if (effect_is_active(&virt_ctxt->common)) { + offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false); + if (virt_ctxt->ctl) + offload_virtualizer_send_params(virt_ctxt->ctl, + virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); + } + ALOGI("%s: ctxt %p, disabled based on device", __func__, virt_ctxt); + virt_ctxt->temp_disabled = true; + } + } else { + if (virt_ctxt->temp_disabled) { + if (effect_is_active(&virt_ctxt->common)) { + offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true); + if (virt_ctxt->ctl) + offload_virtualizer_send_params(virt_ctxt->ctl, + virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); + } + virt_ctxt->temp_disabled = false; + } + } + } + // else virtualization mode is forced to a certain device, nothing to do + + offload_virtualizer_set_device(&(virt_ctxt->offload_virt), device); + return 0; +} + +int virtualizer_reset(effect_context_t *context) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + return 0; +} + +int virtualizer_init(effect_context_t *context) +{ + ALOGV("%s: ctxt %p", __func__, context); + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; + context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; + context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; + context->config.inputCfg.samplingRate = 44100; + context->config.inputCfg.bufferProvider.getBuffer = NULL; + context->config.inputCfg.bufferProvider.releaseBuffer = NULL; + context->config.inputCfg.bufferProvider.cookie = NULL; + context->config.inputCfg.mask = EFFECT_CONFIG_ALL; + context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; + context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; + context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; + context->config.outputCfg.samplingRate = 44100; + context->config.outputCfg.bufferProvider.getBuffer = NULL; + context->config.outputCfg.bufferProvider.releaseBuffer = NULL; + context->config.outputCfg.bufferProvider.cookie = NULL; + context->config.outputCfg.mask = EFFECT_CONFIG_ALL; + + set_config(context, &context->config); + + virt_ctxt->temp_disabled = false; + virt_ctxt->forced_device = AUDIO_DEVICE_NONE; + virt_ctxt->device = AUDIO_DEVICE_NONE; + memset(&(virt_ctxt->offload_virt), 0, sizeof(struct virtualizer_params)); + + return 0; +} + +int virtualizer_enable(effect_context_t *context) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + ALOGV("%s: ctxt %p, strength %d", __func__, virt_ctxt, virt_ctxt->strength); + + 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, + virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG | + OFFLOAD_SEND_BASSBOOST_STRENGTH); + } + return 0; +} + +int virtualizer_disable(effect_context_t *context) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + ALOGV("%s: ctxt %p", __func__, virt_ctxt); + if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) { + offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false); + if (virt_ctxt->ctl) + offload_virtualizer_send_params(virt_ctxt->ctl, + virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); + } + return 0; +} + +int virtualizer_start(effect_context_t *context, output_context_t *output) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + ALOGV("%s: ctxt %p, ctl %p", __func__, virt_ctxt, output->ctl); + virt_ctxt->ctl = output->ctl; + if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) + if (virt_ctxt->ctl) + offload_virtualizer_send_params(virt_ctxt->ctl, virt_ctxt->offload_virt, + OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG | + OFFLOAD_SEND_VIRTUALIZER_STRENGTH); + return 0; +} + +int virtualizer_stop(effect_context_t *context, output_context_t *output __unused) +{ + virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; + + ALOGV("%s: ctxt %p", __func__, virt_ctxt); + virt_ctxt->ctl = NULL; + return 0; +} |