Merge "hal: use separate dual mic config for qrd device during voip call"
diff --git a/configs/msmnile_au/mixer_paths_adp.xml b/configs/msmnile_au/mixer_paths_adp.xml
index bcea162..e5ce0ab 100644
--- a/configs/msmnile_au/mixer_paths_adp.xml
+++ b/configs/msmnile_au/mixer_paths_adp.xml
@@ -318,6 +318,10 @@
<ctl name="SEC_TDM_RX_0 Audio Mixer MultiMedia9" value="0" />
<ctl name="MultiMedia9 Mixer TERT_TDM_TX_0" value="0" />
+ <path name="dummy-hostless">
+ <ctl name="SEC_TDM_RX_7 Port Mixer TERT_TDM_TX_7" value="1" />
+ </path>
+
<!-- Codec controls -->
<!-- WSA controls -->
<ctl name="SpkrLeft COMP Switch" value="0" />
diff --git a/configs/msmsteppe/audio_platform_info_qrd.xml b/configs/msmsteppe/audio_platform_info_qrd.xml
index 0e7dffc..61d6782 100644
--- a/configs/msmsteppe/audio_platform_info_qrd.xml
+++ b/configs/msmsteppe/audio_platform_info_qrd.xml
@@ -93,6 +93,7 @@
<device name="SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1" acdb_id="10"/>
<device name="SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2" acdb_id="10"/>
<device name="SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET" acdb_id="45"/>
+ <device name="SND_DEVICE_IN_UNPROCESSED_USB_HEADSET_MIC" acdb_id="133"/>
<device name="SND_DEVICE_IN_UNPROCESSED_MIC" acdb_id="143"/>
<device name="SND_DEVICE_IN_UNPROCESSED_STEREO_MIC" acdb_id="144"/>
<device name="SND_DEVICE_IN_UNPROCESSED_THREE_MIC" acdb_id="145"/>
diff --git a/hal/Android.mk b/hal/Android.mk
index 7a0c69f..febba73 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -65,6 +65,10 @@
endif
endif
+ifeq ($(TARGET_BOARD_AUTO),true)
+ LOCAL_CFLAGS += -DPLATFORM_AUTO
+endif
+
LOCAL_CFLAGS += -Wno-macro-redefined
LOCAL_HEADER_LIBRARIES := libhardware_headers
@@ -427,6 +431,11 @@
LOCAL_SRC_FILES += audio_extn/sndmonitor.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_HW_PLUGIN)),true)
+ LOCAL_CFLAGS += -DEXT_HW_PLUGIN_ENABLED
+ LOCAL_SRC_FILES += audio_extn/ext_hw_plugin.c
+endif
+
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_RELATIVE_PATH := hw
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
old mode 100755
new mode 100644
index d125b2f..ba096c9
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -884,6 +884,7 @@
adev->offload_effects_set_parameters(parms);
audio_extn_set_aptx_dec_bt_addr(adev, parms);
audio_extn_ffv_set_parameters(adev, parms);
+ audio_extn_ext_hw_plugin_set_parameters(adev->ext_hw_plugin, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -902,6 +903,7 @@
audio_extn_sound_trigger_get_parameters(adev, query, reply);
if (adev->offload_effects_get_parameters != NULL)
adev->offload_effects_get_parameters(query, reply);
+ audio_extn_ext_hw_plugin_get_parameters(adev->ext_hw_plugin, query, reply);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index a3b374c..e74bd36 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -1107,4 +1107,29 @@
snd_device_t audio_extn_ffv_get_capture_snd_device();
void audio_extn_ffv_append_ec_ref_dev_name(char *device_name);
#endif
+
+#ifndef EXT_HW_PLUGIN_ENABLED
+#define audio_extn_ext_hw_plugin_init(adev) (0)
+#define audio_extn_ext_hw_plugin_deinit(plugin) (0)
+#define audio_extn_ext_hw_plugin_usecase_start(plugin, usecase) (0)
+#define audio_extn_ext_hw_plugin_usecase_stop(plugin, usecase) (0)
+#define audio_extn_ext_hw_plugin_set_parameters(plugin, parms) (0)
+#define audio_extn_ext_hw_plugin_get_parameters(plugin, query, reply) (0)
+#define audio_extn_ext_hw_plugin_set_mic_mute(plugin, mute) (0)
+#define audio_extn_ext_hw_plugin_get_mic_mute(plugin, mute) (0)
+#define audio_extn_ext_hw_plugin_set_audio_gain(plugin, usecase, gain) (0)
+#else
+void* audio_extn_ext_hw_plugin_init(struct audio_device *adev);
+int audio_extn_ext_hw_plugin_deinit(void *plugin);
+int audio_extn_ext_hw_plugin_usecase_start(void *plugin, struct audio_usecase *usecase);
+int audio_extn_ext_hw_plugin_usecase_stop(void *plugin, struct audio_usecase *usecase);
+int audio_extn_ext_hw_plugin_set_parameters(void *plugin,
+ struct str_parms *parms);
+int audio_extn_ext_hw_plugin_get_parameters(void *plugin,
+ struct str_parms *query, struct str_parms *reply);
+int audio_extn_ext_hw_plugin_set_mic_mute(void *plugin, bool mute);
+int audio_extn_ext_hw_plugin_get_mic_mute(void *plugin, bool *mute);
+int audio_extn_ext_hw_plugin_set_audio_gain(void *plugin,
+ struct audio_usecase *usecase, uint32_t gain);
+#endif
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/ext_hw_plugin.c b/hal/audio_extn/ext_hw_plugin.c
new file mode 100644
index 0000000..3c9458a
--- /dev/null
+++ b/hal/audio_extn/ext_hw_plugin.c
@@ -0,0 +1,1595 @@
+/* ext_hw_plugin.c
+Copyright (c) 2014-2016 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
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
+
+#define LOG_TAG "audio_ext_hw_plugin"
+#define LOG_NDEBUG 0
+
+#include <errno.h>
+#include <pthread.h>
+#include <dlfcn.h>
+#include <cutils/log.h>
+#include <audio_hw.h>
+#include "audio_extn.h"
+#include "platform_api.h"
+#include "platform.h"
+#include "audio_hal_plugin.h"
+
+
+#ifdef EXT_HW_PLUGIN_ENABLED
+
+typedef int32_t (*audio_hal_plugin_init_t)(void);
+typedef int32_t (*audio_hal_plugin_deinit_t)(void);
+typedef int32_t (*audio_hal_plugin_send_msg_t)(audio_hal_plugin_msg_type_t,
+ void *, uint32_t);
+
+struct ext_hw_plugin_data {
+ struct audio_device *adev;
+ void *plugin_handle;
+ audio_hal_plugin_init_t audio_hal_plugin_init;
+ audio_hal_plugin_deinit_t audio_hal_plugin_deinit;
+ audio_hal_plugin_send_msg_t audio_hal_plugin_send_msg;
+ int32_t usecase_ref_count[AUDIO_HAL_PLUGIN_USECASE_MAX];
+ snd_device_t out_snd_dev[AUDIO_HAL_PLUGIN_USECASE_MAX];
+ snd_device_t in_snd_dev[AUDIO_HAL_PLUGIN_USECASE_MAX];
+ bool mic_mute;
+};
+
+/* This can be defined in platform specific file or use compile flag */
+#define LIB_PLUGIN_DRIVER "libaudiohalplugin.so"
+
+/* Note: Due to ADP H/W design, SoC TERT/SEC TDM CLK and FSYNC lines are both connected
+ * with CODEC and a single master is needed to provide consistent CLK and FSYNC to slaves,
+ * hence configuring SoC TERT TDM as single master and bring up a dummy hostless from TERT
+ * to SEC to ensure both slave SoC SEC TDM and CODEC are driven upon system boot. */
+static void audio_extn_ext_hw_plugin_enable_adev_hostless(struct audio_device *adev)
+{
+ ALOGI("%s: Enable TERT -> SEC Hostless", __func__);
+
+ char mixer_path[MIXER_PATH_MAX_LENGTH];
+ strlcpy(mixer_path, "dummy-hostless", MIXER_PATH_MAX_LENGTH);
+ ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
+ audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+
+ /* TERT TDM TX 7 HOSTLESS to SEC TDM RX 7 HOSTLESS */
+ int pcm_dev_rx = 48, pcm_dev_tx = 49;
+ struct pcm_config pcm_config_lb = {
+ .channels = 1,
+ .rate = 48000,
+ .period_size = 240,
+ .period_count = 2,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = 0,
+ .stop_threshold = INT_MAX,
+ .avail_min = 0,
+ };
+
+ struct pcm *pcm_tx = pcm_open(adev->snd_card,
+ pcm_dev_tx,
+ PCM_IN, &pcm_config_lb);
+ if (pcm_tx && !pcm_is_ready(pcm_tx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(pcm_tx));
+ return;
+ }
+ struct pcm *pcm_rx = pcm_open(adev->snd_card,
+ pcm_dev_rx,
+ PCM_OUT, &pcm_config_lb);
+ if (pcm_rx && !pcm_is_ready(pcm_rx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(pcm_rx));
+ return;
+ }
+
+ if (pcm_start(pcm_tx) < 0) {
+ ALOGE("%s: pcm start for pcm tx failed", __func__);
+ return;
+ }
+ if (pcm_start(pcm_rx) < 0) {
+ ALOGE("%s: pcm start for pcm rx failed", __func__);
+ return;
+ }
+}
+
+void* audio_extn_ext_hw_plugin_init(struct audio_device *adev)
+{
+ int32_t ret = 0;
+ struct ext_hw_plugin_data *my_plugin = NULL;
+
+ my_plugin = calloc(1, sizeof(struct ext_hw_plugin_data));
+
+ if (my_plugin == NULL) {
+ ALOGE("[%s] Memory allocation failed for plugin data",__func__);
+ return NULL;
+ }
+
+ my_plugin->adev = adev;
+
+ my_plugin->plugin_handle = dlopen(LIB_PLUGIN_DRIVER, RTLD_NOW);
+ if (my_plugin->plugin_handle == NULL) {
+ ALOGE("%s: DLOPEN failed for %s", __func__, LIB_PLUGIN_DRIVER);
+ goto plugin_init_fail;
+ } else {
+ ALOGV("%s: DLOPEN successful for %s", __func__, LIB_PLUGIN_DRIVER);
+ my_plugin->audio_hal_plugin_init = (audio_hal_plugin_init_t)dlsym(
+ my_plugin->plugin_handle, "audio_hal_plugin_init");
+ if (!my_plugin->audio_hal_plugin_init) {
+ ALOGE("%s: Could not find the symbol audio_hal_plugin_init from %s",
+ __func__, LIB_PLUGIN_DRIVER);
+ goto plugin_init_fail;
+ }
+
+ my_plugin->audio_hal_plugin_deinit = (audio_hal_plugin_deinit_t)dlsym(
+ my_plugin->plugin_handle, "audio_hal_plugin_deinit");
+ if (!my_plugin->audio_hal_plugin_deinit) {
+ ALOGE("%s: Could not find the symbol audio_hal_plugin_deinit from %s",
+ __func__, LIB_PLUGIN_DRIVER);
+ goto plugin_init_fail;
+ }
+
+ my_plugin->audio_hal_plugin_send_msg = (audio_hal_plugin_send_msg_t)
+ dlsym(my_plugin->plugin_handle, "audio_hal_plugin_send_msg");
+ if (!my_plugin->audio_hal_plugin_send_msg) {
+ ALOGE("%s: Could not find the symbol audio_hal_plugin_send_msg from %s",
+ __func__, LIB_PLUGIN_DRIVER);
+ goto plugin_init_fail;
+ }
+
+ ret = my_plugin->audio_hal_plugin_init();
+ if (ret) {
+ ALOGE("%s: audio_hal_plugin_init failed with ret = %d",
+ __func__, ret);
+ goto plugin_init_fail;
+ }
+ }
+
+ audio_extn_ext_hw_plugin_enable_adev_hostless(adev);
+
+ my_plugin->mic_mute = false;
+ return my_plugin;
+
+plugin_init_fail:
+ if (my_plugin->plugin_handle != NULL)
+ dlclose(my_plugin->plugin_handle);
+ free(my_plugin);
+ return NULL;
+}
+
+int32_t audio_extn_ext_hw_plugin_deinit(void *plugin)
+{
+ int32_t ret = 0;
+ struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin;
+
+ if (my_plugin == NULL) {
+ ALOGE("[%s] NULL plugin pointer",__func__);
+ return -EINVAL;
+ }
+
+ if (my_plugin->audio_hal_plugin_deinit) {
+ ret = my_plugin->audio_hal_plugin_deinit();
+ if (ret) {
+ ALOGE("%s: audio_hal_plugin_deinit failed with ret = %d",
+ __func__, ret);
+ }
+ }
+ if(my_plugin->plugin_handle != NULL)
+ dlclose(my_plugin->plugin_handle);
+
+ free(my_plugin);
+ return ret;
+}
+
+static int32_t ext_hw_plugin_check_plugin_usecase(audio_usecase_t hal_usecase,
+ audio_hal_plugin_usecase_type_t *plugin_usecase)
+{
+ int32_t ret = 0;
+
+ switch(hal_usecase) {
+ case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
+ case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
+ case USECASE_AUDIO_PLAYBACK_MULTI_CH:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD:
+#ifdef MULTIPLE_OFFLOAD_ENABLED
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD3:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD4:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD5:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD6:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD7:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD8:
+ case USECASE_AUDIO_PLAYBACK_OFFLOAD9:
+#endif
+ case USECASE_AUDIO_PLAYBACK_ULL:
+ *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_PLAYBACK;
+ break;
+ case USECASE_AUDIO_RECORD:
+ case USECASE_AUDIO_RECORD_COMPRESS:
+ case USECASE_AUDIO_RECORD_LOW_LATENCY:
+ case USECASE_AUDIO_RECORD_FM_VIRTUAL:
+ *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_CAPTURE;
+ break;
+ case USECASE_AUDIO_HFP_SCO:
+ case USECASE_AUDIO_HFP_SCO_WB:
+ *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL;
+ break;
+ case USECASE_VOICE_CALL:
+ case USECASE_VOICEMMODE1_CALL:
+ *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_CS_VOICE_CALL;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int32_t audio_extn_ext_hw_plugin_usecase_start(void *plugin, struct audio_usecase *usecase)
+{
+ int32_t ret = 0;
+ struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin;
+
+ if ((my_plugin == NULL) || (usecase == NULL)) {
+ ALOGE("[%s] NULL input pointer",__func__);
+ return -EINVAL;
+ }
+
+ if (my_plugin->audio_hal_plugin_send_msg) {
+ audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_ENABLE;
+ audio_hal_plugin_codec_enable_t codec_enable;
+
+ ret = ext_hw_plugin_check_plugin_usecase(usecase->id, &codec_enable.usecase);
+ if(ret){
+ ALOGI("%s: enable audio hal plugin skipped for audio usecase %d",
+ __func__, usecase->id);
+ return 0;
+ }
+
+ if(usecase->id == USECASE_AUDIO_RECORD) {
+ if(usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC) {
+ codec_enable.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_CAPTURE;
+ }
+ }
+
+ if(my_plugin->usecase_ref_count[codec_enable.usecase]){
+ ALOGV("%s: plugin usecase %d already enabled",
+ __func__, codec_enable.usecase);
+ my_plugin->usecase_ref_count[codec_enable.usecase]++;
+ return 0;
+ }
+
+ if ((usecase->type == PCM_CAPTURE) || (usecase->type == VOICE_CALL) ||
+ (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL)) {
+ codec_enable.snd_dev = usecase->in_snd_device;
+ /* TODO - below should be related with in_snd_dev */
+ codec_enable.sample_rate = 48000;
+ codec_enable.bit_width = 16;
+ codec_enable.num_chs = 2;
+
+ ALOGD("%s: enable audio hal plugin input, %d, %d, %d, %d, %d",
+ __func__, (int)codec_enable.usecase,
+ (int)codec_enable.snd_dev,
+ (int)codec_enable.sample_rate,
+ (int)codec_enable.bit_width,
+ (int)codec_enable.num_chs);
+ ret = my_plugin->audio_hal_plugin_send_msg(msg,
+ (void*)&codec_enable, sizeof(codec_enable));
+ if (ret) {
+ ALOGE("%s: enable audio hal plugin input failed ret = %d",
+ __func__, ret);
+ return ret;
+ }
+ my_plugin->in_snd_dev[codec_enable.usecase] = codec_enable.snd_dev;
+
+ if (my_plugin->mic_mute &&
+ codec_enable.usecase == AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL) {
+ int plugin_ret;
+ audio_hal_plugin_codec_set_pp_mute_t pp_mute;
+
+ pp_mute.usecase = codec_enable.usecase;
+ pp_mute.snd_dev = codec_enable.snd_dev;
+ pp_mute.ch_mask = AUDIO_CHANNEL_IN_ALL;
+ pp_mute.flag = my_plugin->mic_mute;
+
+ ALOGV("%s: sending codec pp mute msg to HAL plugin driver, %d, %d, %x, %d",
+ __func__, (int)pp_mute.usecase, (int)pp_mute.snd_dev,
+ (int)pp_mute.ch_mask, (int)pp_mute.flag);
+ plugin_ret = my_plugin->audio_hal_plugin_send_msg(
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE, &pp_mute,
+ sizeof(pp_mute));
+ if (plugin_ret)
+ ALOGE("%s: Failed to set plugin pp mute err: %d", __func__, plugin_ret);
+ }
+ }
+
+ if ((usecase->type == PCM_CAPTURE) &&
+ (usecase->id == USECASE_AUDIO_RECORD) &&
+ (usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC)) {
+ audio_hal_plugin_codec_enable_t codec_enable_ec = {0,};
+ codec_enable_ec.snd_dev = usecase->in_snd_device;
+ // TODO - below should be related with in_snd_dev
+ codec_enable_ec.sample_rate = 48000;
+ codec_enable_ec.bit_width = 16;
+ codec_enable_ec.num_chs = 6;
+ codec_enable_ec.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_REF_CAPTURE;
+
+ ALOGD("%s: enable audio hal plugin input for echo reference, %d, %d, %d, %d, %d",
+ __func__, (int)codec_enable_ec.usecase,
+ (int)codec_enable_ec.snd_dev,
+ (int)codec_enable_ec.sample_rate,
+ (int)codec_enable_ec.bit_width,
+ (int)codec_enable_ec.num_chs);
+ ret = my_plugin->audio_hal_plugin_send_msg(msg,
+ (void*)&codec_enable_ec, sizeof(codec_enable_ec));
+ if (ret) {
+ ALOGE("%s: enable audio hal plugin input failed ret = %d",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ if ((usecase->type == PCM_PLAYBACK) || (usecase->type == VOICE_CALL) ||
+ (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL)) {
+ codec_enable.snd_dev = usecase->out_snd_device;
+ /* TODO - below should be related with out_snd_dev */
+ codec_enable.sample_rate = 48000;
+ codec_enable.bit_width = 24;
+ codec_enable.num_chs = 2;
+
+ ALOGD("%s: enable audio hal plugin output, %d, %d, %d, %d, %d",
+ __func__, (int)codec_enable.usecase,
+ (int)codec_enable.snd_dev,
+ (int)codec_enable.sample_rate,
+ (int)codec_enable.bit_width,
+ (int)codec_enable.num_chs);
+ ret = my_plugin->audio_hal_plugin_send_msg(msg,
+ (void*)&codec_enable, sizeof(codec_enable));
+ if (ret) {
+ ALOGE("%s: enable audio hal plugin output failed ret = %d",
+ __func__, ret);
+ return ret;
+ }
+ my_plugin->out_snd_dev[codec_enable.usecase] = codec_enable.snd_dev;
+ }
+ my_plugin->usecase_ref_count[codec_enable.usecase]++;
+ }
+
+ ALOGD("%s: finished ext_hw_plugin usecase start", __func__);
+
+ return ret;
+}
+
+int32_t audio_extn_ext_hw_plugin_usecase_stop(void *plugin, struct audio_usecase *usecase)
+{
+ int32_t ret = 0;
+ struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin;
+
+ if ((my_plugin == NULL) || (usecase == NULL)) {
+ ALOGE("[%s] NULL input pointer",__func__);
+ return -EINVAL;
+ }
+ if (my_plugin->audio_hal_plugin_send_msg) {
+ audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_DISABLE;
+ audio_hal_plugin_codec_disable_t codec_disable;
+
+ ret = ext_hw_plugin_check_plugin_usecase(usecase->id, &codec_disable.usecase);
+ if(ret){
+ ALOGI("%s: disable audio hal plugin skipped for audio usecase %d",
+ __func__, usecase->id);
+ return 0;
+ }
+
+ if((usecase->id == USECASE_AUDIO_RECORD) &&
+ (usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC))
+ {
+ codec_disable.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_CAPTURE;
+ }
+ if(my_plugin->usecase_ref_count[codec_disable.usecase] > 1){
+ ALOGI("%s: plugin usecase %d still in use and can not be disabled",
+ __func__, codec_disable.usecase);
+ my_plugin->usecase_ref_count[codec_disable.usecase]--;
+ return 0;
+ } else if(my_plugin->usecase_ref_count[codec_disable.usecase] < 1){
+ ALOGE("%s: plugin usecase %d not enabled",
+ __func__, codec_disable.usecase);
+ return -EINVAL;
+ }
+
+ if ((usecase->type == PCM_PLAYBACK) || (usecase->type == VOICE_CALL) ||
+ (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL)) {
+ codec_disable.snd_dev = usecase->out_snd_device;
+
+ ALOGD("%s: disable audio hal plugin output, %d, %d",
+ __func__, (int)codec_disable.usecase,
+ (int)codec_disable.snd_dev);
+ ret = my_plugin->audio_hal_plugin_send_msg(msg,
+ (void*)&codec_disable, sizeof(codec_disable));
+ if (ret) {
+ ALOGE("%s: disable audio hal plugin output failed ret = %d",
+ __func__, ret);
+ }
+ my_plugin->out_snd_dev[codec_disable.usecase] = 0;
+ }
+ if ((usecase->type == PCM_CAPTURE) || (usecase->type == VOICE_CALL) ||
+ (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL)) {
+ codec_disable.snd_dev = usecase->in_snd_device;
+
+ ALOGD("%s: disable audio hal plugin input, %d, %d",
+ __func__, (int)codec_disable.usecase,
+ (int)codec_disable.snd_dev);
+ ret = my_plugin->audio_hal_plugin_send_msg(msg,
+ (void*)&codec_disable, sizeof(codec_disable));
+ if (ret) {
+ ALOGE("%s: disable audio hal plugin input failed ret = %d",
+ __func__, ret);
+ }
+ my_plugin->in_snd_dev[codec_disable.usecase] = 0;
+ }
+
+ if ((usecase->type == PCM_CAPTURE) &&
+ (usecase->id == USECASE_AUDIO_RECORD) &&
+ (usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC)) {
+ audio_hal_plugin_codec_disable_t codec_disable_ec = {0,};
+ codec_disable_ec.snd_dev = usecase->in_snd_device;
+ codec_disable_ec.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_REF_CAPTURE;
+
+ ALOGD("%s: disable audio hal plugin input for echo reference, %d, %d",
+ __func__, (int)codec_disable_ec.usecase,
+ (int)codec_disable_ec.snd_dev);
+ ret = my_plugin->audio_hal_plugin_send_msg(msg,
+ (void*)&codec_disable_ec, sizeof(codec_disable_ec));
+ if (ret) {
+ ALOGE("%s: disable audio hal plugin input failed ret = %d",
+ __func__, ret);
+ return ret;
+ }
+ }
+ my_plugin->usecase_ref_count[codec_disable.usecase]--;
+ }
+
+ ALOGD("%s: finished ext_hw_plugin usecase stop", __func__);
+
+ return ret;
+}
+
+static int32_t ext_hw_plugin_string_to_dword(char *string_value, void **dword_ptr,
+ uint32_t dword_len)
+{
+ int32_t ret = 0;
+ uint32_t i,tmp;
+ uint8_t *dptr = NULL;
+ uint8_t *tmpptr = NULL;
+ int32_t dlen;
+ uint32_t *outptr = NULL;
+
+ dlen = strlen(string_value);
+ if (dlen <= 0) {
+ ALOGE("%s: NULL data received", __func__);
+ return -EINVAL;
+ }
+ dptr = (uint8_t*) calloc(dlen, sizeof(uint8_t));
+ if (dptr == NULL) {
+ ALOGE("%s: memory allocation failed", __func__);
+ return -ENOMEM;
+ }
+ dlen = b64decode(string_value, strlen(string_value), dptr);
+ if ((dlen <= 0) || ((uint32_t)dlen != 4*dword_len)){
+ ALOGE("%s: data decoding failed", __func__);
+ ret = -EINVAL;
+ goto done_string_to_dword;
+ }
+
+ outptr = calloc(dword_len, sizeof(uint32_t));
+ if (outptr == NULL) {
+ ALOGE("%s: memory allocation failed", __func__);
+ ret = -ENOMEM;
+ goto done_string_to_dword;
+ }
+
+ for(i=0; i<dword_len; i++) {
+ tmpptr = dptr+4*i;
+ tmp = (uint32_t) *(tmpptr);
+ tmp |= ((uint32_t) *(tmpptr+1))<<8;
+ tmp |= ((uint32_t) *(tmpptr+2))<<16;
+ tmp |= ((uint32_t) *(tmpptr+3))<<24;
+ *(outptr + i) = tmp;
+ }
+ *dword_ptr = (void*)outptr;
+
+done_string_to_dword:
+ if (dptr != NULL)
+ free(dptr);
+
+ return ret;
+}
+
+static int32_t ext_hw_plugin_dword_to_string(uint32_t *dword_ptr, uint32_t dword_len,
+ char **string_ptr)
+{
+ int32_t ret = 0;
+ uint32_t i,tmp;
+ uint8_t *dptr = NULL;
+ uint8_t *tmpptr = NULL;
+ int32_t dlen;
+ char *outptr = NULL;
+
+ dptr = (uint8_t*)calloc(dword_len, sizeof(uint32_t));
+ if(dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,dword_len);
+ return -ENOMEM;
+ }
+
+ /* convert dword to byte array */
+ for(i=0; i<dword_len; i++) {
+ tmp = *(dword_ptr + i);
+ tmpptr = dptr+4*i;
+ *tmpptr = (uint8_t) (tmp & 0xFF);
+ *(tmpptr + 1) = (uint8_t) ((tmp>>8) & 0xFF);
+ *(tmpptr + 2) = (uint8_t) ((tmp>>16) & 0xFF);
+ *(tmpptr + 3) = (uint8_t) ((tmp>>24) & 0xFF);
+ }
+
+ /* Allocate memory for encoding */
+ dlen = dword_len * 4;
+ outptr = (char*)calloc((dlen*2), sizeof(char));
+ if(outptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for size %d",
+ __func__, dlen*2);
+ ret = -ENOMEM;
+ goto done_dword_to_string;
+ }
+
+ ret = b64encode(dptr, dlen, outptr);
+ if(ret < 0) {
+ ALOGE("[%s] failed to convert data to string ret = %d", __func__, ret);
+ free(outptr);
+ ret = -EINVAL;
+ goto done_dword_to_string;
+ }
+ *string_ptr = outptr;
+
+done_dword_to_string:
+ if (dptr != NULL)
+ free(dptr);
+
+ return ret;
+}
+
+
+int32_t audio_extn_ext_hw_plugin_set_parameters(void *plugin, struct str_parms *parms)
+{
+
+ char *value = NULL;
+ int32_t val, len = 0;
+ int32_t ret = 0, err;
+ char *kv_pairs = NULL;
+ struct ext_hw_plugin_data *my_plugin = NULL;
+
+ if (plugin == NULL || parms == NULL) {
+ ALOGE("[%s] received null pointer",__func__);
+ return -EINVAL;
+ }
+
+ my_plugin = (struct ext_hw_plugin_data *)plugin;
+ if (!my_plugin->audio_hal_plugin_send_msg) {
+ ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__);
+ return -EINVAL;
+ }
+
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE, &val);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing TYPE param for plugin msg", __func__);
+ return -EINVAL;
+ }
+ ALOGD("%s: received plugin msg type (%d)", __func__, val);
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE);
+
+ if(val == AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD ||
+ val == AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ) {
+ kv_pairs = str_parms_to_str(parms);
+ len = strlen(kv_pairs);
+ value = (char*)calloc(len, sizeof(char));
+ if (value == NULL) {
+ ret = -ENOMEM;
+ ALOGE("[%s] failed to allocate memory",__func__);
+ goto done;
+ }
+ }
+
+ if (val == AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD) {
+ uint32_t plsize;
+ int32_t *plptr = NULL;
+
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE,
+ (int*)&plsize);
+ if ((err < 0) || (!plsize)) {
+ ALOGE("%s: Invalid or missing size param for TUNNEL command", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE);
+
+ err = str_parms_get_str(parms,
+ AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA, value, len);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing band_data for TUNNEL command", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA);
+
+ ret = ext_hw_plugin_string_to_dword(value, (void**)&plptr, plsize);
+ if (ret) {
+ ALOGE("%s: Failed to parse payload for TUNNEL command", __func__);
+ ret = -EINVAL;
+ goto done_tunnel;
+ }
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD;
+
+ ALOGD("%s: sending codec tunnel cmd msg to HAL plugin driver,size = %d",
+ __func__, (int)plsize);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, (void*)plptr, plsize);
+ if (ret) {
+ ALOGE("%s: Failed to send plugin tunnel cmd err: %d", __func__, ret);
+ }
+
+done_tunnel:
+ if (plptr!= NULL)
+ free(plptr);
+ } else {
+ audio_hal_plugin_usecase_type_t use_case;
+ audio_hal_plugin_direction_type_t dir;
+ snd_device_t snd_dev = 0;
+
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC,
+ &use_case);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing usecase param for plugin msg", __func__);
+ ret = -EINVAL;
+ /* TODO: do we need to support no use case in kvpair? */
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC);
+ if ((use_case < 0) || (use_case >= AUDIO_HAL_PLUGIN_USECASE_MAX)) {
+ ALOGE("%s: Invalid usecase param for plugin msg", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (my_plugin->usecase_ref_count[use_case] == 0) {
+ /* allow param set when usecase not enabled */
+ ALOGI("%s: plugin usecase (%d) is not enabled", __func__, use_case);
+ } else {
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_DIRECTION,
+ &dir);
+ if (err < 0) {
+ if (my_plugin->out_snd_dev[use_case]) {
+ snd_dev = my_plugin->out_snd_dev[use_case];
+ } else if (my_plugin->in_snd_dev[use_case]) {
+ snd_dev = my_plugin->in_snd_dev[use_case];
+ } else {
+ ALOGE("%s: No valid snd_device found for the usecase (%d)",
+ __func__, use_case);
+ ret = -EINVAL;
+ goto done;
+ }
+ } else {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_DIRECTION);
+
+ switch(dir) {
+ case AUDIO_HAL_PLUGIN_DIRECTION_PLAYBACK:
+ {
+ if (!my_plugin->out_snd_dev[use_case]) {
+ ALOGE("%s: No valid out_snd_device found for playback (%d)",
+ __func__, use_case);
+ ret = -EINVAL;
+ goto done;
+ }
+ snd_dev = my_plugin->out_snd_dev[use_case];
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_DIRECTION_CAPTURE:
+ {
+ if (!my_plugin->in_snd_dev[use_case]) {
+ ALOGE("%s: No valid in_snd_device found for capture (%d)",
+ __func__, use_case);
+ ret = -EINVAL;
+ goto done;
+ }
+ snd_dev = my_plugin->in_snd_dev[use_case];
+ break;
+ }
+ default:
+ ALOGE("%s: Invalid direction param for plugin msg", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+ }
+
+ switch(val) {
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME:
+ {
+ audio_hal_plugin_codec_set_pp_vol_t pp_vol;
+ memset(&pp_vol,0,sizeof(pp_vol));
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK,
+ (int*)&pp_vol.ch_mask);
+ if ((err < 0)) {
+ /* TODO: properly handle no cmask param from client case */
+ ALOGE("%s: Invalid or missing CMASK param for SET_PP_VOLUME", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK);
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GAIN,
+ (int*)&pp_vol.gain);
+ if ((err < 0)) {
+ /* TODO: properly handle no gain param from client case */
+ ALOGE("%s: Invalid or missing GAIN param for SET_PP_VOLUME", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GAIN);
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME;
+ pp_vol.usecase = use_case;
+ pp_vol.snd_dev= snd_dev;
+
+ ALOGD("%s: sending codec pp vol msg to HAL plugin driver, %d, %d, %d, %d",
+ __func__, (int)pp_vol.usecase, (int)pp_vol.snd_dev,
+ (int)pp_vol.ch_mask, (int)pp_vol.gain);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_vol, sizeof(pp_vol));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp vol err: %d", __func__, ret);
+ }
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE:
+ {
+ int32_t flag;
+ audio_hal_plugin_codec_set_pp_mute_t pp_mute;
+ memset(&pp_mute,0,sizeof(pp_mute));
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK,
+ (int*)&pp_mute.ch_mask);
+ if ((err < 0)) {
+ /* TODO: properly handle no cmask param from client case */
+ ALOGE("%s: Invalid or missing CMASK param for SET_PP_MUTE", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK);
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MUTE_FLAG,
+ (int*)&flag);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing FLAG param for SET_PP_MUTE", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MUTE_FLAG);
+ pp_mute.flag = (bool)flag;
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE;
+ pp_mute.usecase = use_case;
+ pp_mute.snd_dev= snd_dev;
+
+ ALOGD("%s: sending codec pp mute msg to HAL plugin driver, %d, %d, %d, %d",
+ __func__, (int)pp_mute.usecase, (int)pp_mute.snd_dev,
+ (int)pp_mute.ch_mask, (int)pp_mute.flag);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_mute,
+ sizeof(pp_mute));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp vol err: %d", __func__, ret);
+ }
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_FADE:
+ {
+ audio_hal_plugin_codec_set_pp_fade_t pp_fade;
+ memset(&pp_fade,0,sizeof(pp_fade));
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_FADE,
+ (int*)&pp_fade.fade);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing FADE param for SET_PP_FADE", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_FADE);
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_FADE;
+ pp_fade.usecase = use_case;
+ pp_fade.snd_dev= snd_dev;
+
+ ALOGD("%s: sending codec pp fade msg to HAL plugin driver, %d, %d, %d",
+ __func__, (int)pp_fade.usecase, (int)pp_fade.snd_dev,
+ (int)pp_fade.fade);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_fade,
+ sizeof(pp_fade));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp fade err: %d", __func__, ret);
+ }
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BALANCE:
+ {
+ audio_hal_plugin_codec_set_pp_balance_t pp_balance;
+ memset(&pp_balance,0,sizeof(pp_balance));
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BALANCE,
+ (int*)&pp_balance.balance);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing balance param for SET_PP_BALANCE", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BALANCE);
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BALANCE;
+ pp_balance.usecase = use_case;
+ pp_balance.snd_dev= snd_dev;
+
+ ALOGD("%s: sending codec pp balance msg to HAL plugin driver, %d, %d, %d",
+ __func__, (int)pp_balance.usecase, (int)pp_balance.snd_dev,
+ (int)pp_balance.balance);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_balance,
+ sizeof(pp_balance));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp balance err: %d", __func__, ret);
+ }
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BMT:
+ {
+ int32_t filter_type, enable_flag;
+ audio_hal_plugin_codec_set_pp_bmt_t pp_bmt;
+ memset(&pp_bmt,0,sizeof(pp_bmt));
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE,
+ (int*)&filter_type);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing filter type param for SET_PP_BMT", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE);
+ if ((filter_type <= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID) &&
+ (filter_type >= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_MAX)) {
+ ALOGE("%s: Invalid filter type value for SET_PP_BMT", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ pp_bmt.filter_type = filter_type;
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FLAG,
+ (int*)&enable_flag);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing enable flag param for SET_PP_BMT", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FLAG);
+ pp_bmt.enable_flag = (bool)enable_flag;
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_VAL,
+ (int*)&pp_bmt.value);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing value param for SET_PP_BMT", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_VAL);
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BMT;
+ pp_bmt.usecase = use_case;
+ pp_bmt.snd_dev= snd_dev;
+
+ ALOGD("%s: sending codec pp bmt msg to HAL plugin driver,%d,%d,%d,%d,%d",
+ __func__, (int)pp_bmt.usecase, (int)pp_bmt.snd_dev,
+ (int)pp_bmt.filter_type, (int)pp_bmt.enable_flag,
+ (int)pp_bmt.value);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_bmt,
+ sizeof(pp_bmt));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp bmt err: %d", __func__, ret);
+ }
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ:
+ {
+ int32_t enable_flag;
+ audio_hal_plugin_codec_set_pp_eq_t pp_eq;
+ memset(&pp_eq,0,sizeof(pp_eq));
+
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_FLAG,
+ (int*)&enable_flag);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing enable flag param for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_FLAG);
+ pp_eq.enable_flag = (bool)enable_flag;
+
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_ID,
+ (int*)&pp_eq.preset_id);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing preset_id param for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_ID);
+ if (pp_eq.preset_id < -1) {
+ ALOGE("%s: Invalid preset_id param for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (pp_eq.preset_id == -1) {
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS,
+ (int*)&pp_eq.num_bands);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing num_bands param for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS);
+ if (!pp_eq.num_bands) {
+ ALOGE("%s: Invalid num_bands param for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ err = str_parms_get_str(parms,
+ AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_BAND_DATA, value, len);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing band_data for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_BAND_DATA);
+
+ ret = ext_hw_plugin_string_to_dword(value, (void**)&pp_eq.bands,
+ 3*pp_eq.num_bands);
+ if (ret) {
+ ALOGE("%s: Failed to parse band info for SET_PP_EQ", __func__);
+ ret = -EINVAL;
+ goto done_eq;
+ }
+ }
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ;
+ pp_eq.usecase = use_case;
+ pp_eq.snd_dev= snd_dev;
+
+ ALOGD("%s: sending codec pp eq msg to HAL plugin driver,%d,%d,%d,%d,%d",
+ __func__, (int)pp_eq.usecase, (int)pp_eq.snd_dev,
+ (int)pp_eq.enable_flag, (int)pp_eq.preset_id,
+ (int)pp_eq.num_bands);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_eq, sizeof(pp_eq));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp eq err: %d", __func__, ret);
+ }
+
+done_eq:
+ if (pp_eq.bands != NULL)
+ free(pp_eq.bands);
+ break;
+ }
+ default:
+ ALOGE("%s: Invalid plugin message type: %d", __func__, val);
+ ret = -EINVAL;
+ }
+ }
+
+done:
+ ALOGI("%s: exit with code(%d)", __func__, ret);
+ if(kv_pairs != NULL)
+ free(kv_pairs);
+ if(value != NULL)
+ free(value);
+ return ret;
+}
+
+int audio_extn_ext_hw_plugin_get_parameters(void *plugin,
+ struct str_parms *query, struct str_parms *reply)
+{
+ char *value = NULL;
+ int32_t val, len = 0;;
+ int32_t ret = 0, err;
+ int32_t rbuf_dlen = 0;
+ uint32_t *rbuf_dptr = NULL;
+ char *rparms = NULL;
+ audio_hal_plugin_usecase_type_t use_case = AUDIO_HAL_PLUGIN_USECASE_INVALID;
+ snd_device_t snd_dev = 0;
+ struct ext_hw_plugin_data *my_plugin = NULL;
+ char *kv_pairs = NULL;
+
+ if(plugin == NULL || query == NULL || reply == NULL) {
+ ALOGE("[%s] received null pointer",__func__);
+ return -EINVAL;
+ }
+
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE, &val);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing TYPE param for plugin msg", __func__);
+ return -EINVAL;
+ }
+ ALOGD("%s: received plugin msg type (%d)", __func__, val);
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE);
+
+ my_plugin = (struct ext_hw_plugin_data *)plugin;
+ if (!my_plugin->audio_hal_plugin_send_msg) {
+ ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__);
+ ret = -EINVAL;
+ goto done_get_param;
+ }
+
+ if(val == AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD) {
+ kv_pairs = str_parms_to_str(query);
+ len = strlen(kv_pairs);
+ value = (char*)calloc(len, sizeof(char));
+ if (value == NULL) {
+ ret = -ENOMEM;
+ ALOGE("[%s] failed to allocate memory",__func__);
+ goto done_get_param;
+ }
+ } else {
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC,
+ &use_case);
+ if (err < 0) {
+ ALOGI("%s: Invalid or missing usecase param for plugin msg", __func__);
+ use_case = AUDIO_HAL_PLUGIN_USECASE_INVALID;
+ } else {
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC);
+
+ if ((use_case < 0) || (use_case >= AUDIO_HAL_PLUGIN_USECASE_MAX)) {
+ ALOGI("%s: Invalid usecase param for plugin msg", __func__);
+ use_case = AUDIO_HAL_PLUGIN_USECASE_INVALID;
+ goto done_get_param;
+ }
+
+ if (my_plugin->usecase_ref_count[use_case] == 0) {
+ ALOGI("%s: plugin usecase (%d) is not enabled",
+ __func__, use_case);
+ } else {
+ /* TODO: confirm this handles all usecase */
+ if (my_plugin->out_snd_dev[use_case]) {
+ snd_dev = my_plugin->out_snd_dev[use_case];
+ } else if (my_plugin->in_snd_dev[use_case]) {
+ snd_dev = my_plugin->in_snd_dev[use_case];
+ } else {
+ ALOGE("%s: No valid snd_device found for the usecase (%d)",
+ __func__, use_case);
+ ret = -EINVAL;
+ goto done_get_param;
+ }
+ }
+ }
+ }
+
+ switch(val) {
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_VOLUME:
+ {
+ audio_hal_plugin_codec_get_pp_vol_t get_pp_vol;
+ memset(&get_pp_vol,0,sizeof(get_pp_vol));
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK,
+ (int*)&get_pp_vol.ch_mask);
+ if ((err < 0)) {
+ ALOGI("%s: Invalid or missing CMASK param for GET_PP_VOLUME", __func__);
+ get_pp_vol.ch_mask = AUDIO_CHANNEL_NONE;
+ } else {
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK);
+ }
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_VOLUME;
+ get_pp_vol.usecase = use_case;
+ get_pp_vol.snd_dev = snd_dev;
+
+ ALOGD("%s: sending get codec pp vol msg to HAL plugin driver, %d, %d, %d",
+ __func__, (int)get_pp_vol.usecase, (int)get_pp_vol.snd_dev,
+ (int)get_pp_vol.ch_mask);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_vol, sizeof(get_pp_vol));
+ if (ret) {
+ ALOGE("%s: Failed to get plugin pp vol err: %d", __func__, ret);
+ goto done_get_param;
+ }
+
+ rbuf_dlen = sizeof(get_pp_vol.ret_gain)/sizeof(int32_t);
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_get_param;
+ }
+ memcpy(rbuf_dptr, &get_pp_vol.ret_gain, sizeof(get_pp_vol.ret_gain));
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_FADE:
+ {
+ audio_hal_plugin_codec_get_pp_fade_t get_pp_fade;
+ memset(&get_pp_fade,0,sizeof(get_pp_fade));
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_FADE;
+ get_pp_fade.usecase = use_case;
+ get_pp_fade.snd_dev = snd_dev;
+
+ ALOGD("%s: sending get codec pp fade msg to HAL plugin driver, %d, %d",
+ __func__, (int)get_pp_fade.usecase, (int)get_pp_fade.snd_dev);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_fade, sizeof(get_pp_fade));
+ if (ret) {
+ ALOGE("%s: Failed to get plugin pp fade err: %d", __func__, ret);
+ goto done_get_param;
+ }
+
+ rbuf_dlen = sizeof(get_pp_fade.ret_fade)/sizeof(int32_t);
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_get_param;
+ }
+ memcpy(rbuf_dptr, &get_pp_fade.ret_fade, sizeof(get_pp_fade.ret_fade));
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BALANCE:
+ {
+ audio_hal_plugin_codec_get_pp_balance_t get_pp_balance;
+ memset(&get_pp_balance,0,sizeof(get_pp_balance));
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BALANCE;
+ get_pp_balance.usecase = use_case;
+ get_pp_balance.snd_dev = snd_dev;
+
+ ALOGD("%s: sending get codec pp balance msg to HAL plugin driver, %d, %d",
+ __func__, (int)get_pp_balance.usecase, (int)get_pp_balance.snd_dev);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_balance,
+ sizeof(get_pp_balance));
+ if (ret) {
+ ALOGE("%s: Failed to get plugin pp balance err: %d", __func__, ret);
+ goto done_get_param;
+ }
+
+ rbuf_dlen = sizeof(get_pp_balance.ret_balance)/sizeof(int32_t);
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_get_param;
+ }
+ memcpy(rbuf_dptr, &get_pp_balance.ret_balance, sizeof(get_pp_balance.ret_balance));
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BMT:
+ {
+ int32_t filter_type;
+ audio_hal_plugin_codec_get_pp_bmt_t get_pp_bmt;
+ memset(&get_pp_bmt,0,sizeof(get_pp_bmt));
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE,
+ (int*)&filter_type);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing filter type param for GET_PP_BMT", __func__);
+ get_pp_bmt.filter_type = AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID;
+ } else {
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE);
+
+ if ((filter_type <= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID) &&
+ (filter_type >= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_MAX)) {
+ ALOGE("%s: Invalid filter type value for SET_PP_BMT", __func__);
+ get_pp_bmt.filter_type = AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID;
+ } else {
+ get_pp_bmt.filter_type = filter_type;
+ }
+ }
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BMT;
+ get_pp_bmt.usecase = use_case;
+ get_pp_bmt.snd_dev = snd_dev;
+
+ ALOGD("%s: sending get codec pp bmt msg to HAL plugin driver, %d, %d, %d",
+ __func__, (int)get_pp_bmt.usecase, (int)get_pp_bmt.snd_dev,
+ (int)get_pp_bmt.filter_type);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_bmt, sizeof(get_pp_bmt));
+ if (ret) {
+ ALOGE("%s: Failed to get plugin pp bmt err: %d", __func__, ret);
+ goto done_get_param;
+ }
+
+ rbuf_dlen = sizeof(get_pp_bmt.ret_value)/sizeof(int32_t);
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_get_param;
+ }
+ memcpy(rbuf_dptr, &get_pp_bmt.ret_value, sizeof(get_pp_bmt.ret_value));
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ:
+ {
+ uint32_t rbuf_len = 0;
+ char *tmp_ptr = NULL;
+ audio_hal_plugin_codec_get_pp_eq_t get_pp_eq;
+ memset(&get_pp_eq,0,sizeof(get_pp_eq));
+
+ audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ;
+ get_pp_eq.usecase = use_case;
+ get_pp_eq.snd_dev = snd_dev;
+
+ ALOGD("%s: sending get codec pp eq msg to HAL plugin driver, %d, %d",
+ __func__, (int)get_pp_eq.usecase, (int)get_pp_eq.snd_dev);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_eq, sizeof(get_pp_eq));
+ if (ret) {
+ ALOGE("%s: Failed to get plugin pp eq err: %d", __func__, ret);
+ goto done_get_param;
+ }
+
+ rbuf_len = sizeof(get_pp_eq.ret_preset_id) + sizeof(get_pp_eq.ret_num_bands);
+ rbuf_dlen = rbuf_len / sizeof(uint32_t);
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_get_param;
+ }
+ tmp_ptr = (char*)rbuf_dptr;
+ memcpy(tmp_ptr, &get_pp_eq.ret_preset_id, sizeof(get_pp_eq.ret_preset_id));
+ tmp_ptr += sizeof(get_pp_eq.ret_preset_id);
+ memcpy(tmp_ptr, &get_pp_eq.ret_num_bands, sizeof(get_pp_eq.ret_num_bands));
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS:
+ {
+ uint32_t rbuf_len = 0;
+ audio_hal_plugin_codec_get_pp_eq_subbands_t get_pp_eq_subbands;
+ memset(&get_pp_eq_subbands,0,sizeof(get_pp_eq_subbands));
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS,
+ (int*)&get_pp_eq_subbands.num_bands);
+ if ((err < 0)) {
+ ALOGE("%s: Invalid or missing num bands param for GET_PP_EQ_SUBBANDS",
+ __func__);
+ ret = -EINVAL;
+ goto done_get_param;
+ } else {
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS);
+
+ if(get_pp_eq_subbands.num_bands == 0) {
+ ALOGE("%s: Zero num bands param for GET_PP_EQ_SUBBANDS",
+ __func__);
+ ret = -EINVAL;
+ goto done_get_param;
+ }
+ }
+ rbuf_len = get_pp_eq_subbands.num_bands *
+ sizeof(audio_hal_plugin_pp_eq_subband_binfo_t);
+
+ audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS;
+ get_pp_eq_subbands.usecase = use_case;
+ get_pp_eq_subbands.snd_dev = snd_dev;
+ get_pp_eq_subbands.ret_bands = calloc(rbuf_len, 1);
+ if(get_pp_eq_subbands.ret_bands == NULL) {
+ ret = -ENOMEM;
+ ALOGE("[%s] failed to allocate memory",__func__);
+ goto done_get_param;
+ }
+
+ ALOGD("%s: sending get codec pp eq subbands msg to plugin driver, %d, %d, %d",
+ __func__, (int)get_pp_eq_subbands.usecase,
+ (int)get_pp_eq_subbands.snd_dev, (int)get_pp_eq_subbands.num_bands);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_eq_subbands,
+ sizeof(get_pp_eq_subbands));
+ if (ret) {
+ ALOGE("%s: Failed to get plugin pp eq subbands err: %d", __func__, ret);
+ goto done_get_eq_subbands;
+ }
+
+ rbuf_dlen = rbuf_len / sizeof(uint32_t);
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_get_eq_subbands;
+ }
+ memcpy(rbuf_dptr, get_pp_eq_subbands.ret_bands, rbuf_len);
+
+done_get_eq_subbands:
+ if(get_pp_eq_subbands.ret_bands != NULL)
+ free(get_pp_eq_subbands.ret_bands);
+ break;
+ }
+ case AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD:
+ {
+ char *tmp_ptr = NULL;
+ audio_hal_plugin_codec_tunnel_get_t tunnel_get;
+ memset(&tunnel_get,0,sizeof(tunnel_get));
+
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE,
+ (int*)&tunnel_get.param_size);
+ if ((err < 0) || (!tunnel_get.param_size)) {
+ ALOGE("%s: Invalid or missing size param for TUNNEL GET command", __func__);
+ ret = -EINVAL;
+ goto done_get_param;
+ }
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE);
+
+ err = str_parms_get_str(query,
+ AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA, value, len);
+ if (err < 0) {
+ ALOGE("%s: Invalid or missing data param for TUNNEL GET command", __func__);
+ ret = -EINVAL;
+ goto done_get_param;
+ }
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA);
+
+ err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_GET_SIZE,
+ (int*)&tunnel_get.size_to_get);
+ if (err < 0 || (!tunnel_get.size_to_get)) {
+ ALOGE("%s: Invalid or missing size_to_get param for TUNNEL GET command",
+ __func__);
+ ret = -EINVAL;
+ goto done_get_param;
+ }
+ str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_GET_SIZE);
+
+ ret = ext_hw_plugin_string_to_dword(value, (void**)&tunnel_get.param_data,
+ tunnel_get.param_size);
+ if (ret) {
+ ALOGE("%s: Failed to parse payload for TUNNEL GET command", __func__);
+ ret = -EINVAL;
+ goto done_tunnel_get;
+ }
+
+ audio_hal_plugin_msg_type_t msg =
+ AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD;
+ tunnel_get.ret_data = calloc(tunnel_get.size_to_get, sizeof(int32_t));
+ if(tunnel_get.ret_data == NULL) {
+ ret = -ENOMEM;
+ ALOGE("[%s] failed to allocate memory",__func__);
+ goto done_tunnel_get;
+ }
+
+ ALOGD("%s: sending tunnel get cmd to plugin driver,size = %d, size_to_get = %d",
+ __func__, (int)tunnel_get.param_size, (int)tunnel_get.size_to_get);
+
+ ret = my_plugin->audio_hal_plugin_send_msg(msg, (void*)&tunnel_get,
+ sizeof(tunnel_get));
+ if (ret) {
+ ALOGE("%s: Failed to send plugin tunnel get cmd err: %d", __func__, ret);
+ goto done_tunnel_get;
+ }
+ if ((tunnel_get.ret_size == 0) ||
+ (tunnel_get.ret_size > tunnel_get.size_to_get)) {
+ ret = -EINVAL;
+ ALOGE("[%s] Invalid tunnel get cmd return size: %d",
+ __func__, tunnel_get.ret_size);
+ goto done_tunnel_get;
+ }
+
+ rbuf_dlen = tunnel_get.ret_size + 1;
+ rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t));
+ if(rbuf_dptr == NULL) {
+ ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen);
+ ret = -ENOMEM;
+ goto done_tunnel_get;
+ }
+ tmp_ptr = (char*)rbuf_dptr;
+ memcpy(tmp_ptr, &tunnel_get.ret_size, sizeof(uint32_t));
+ tmp_ptr += sizeof(uint32_t);
+ memcpy(tmp_ptr, tunnel_get.ret_data, 4*tunnel_get.ret_size);
+
+done_tunnel_get:
+ if (tunnel_get.param_data!= NULL)
+ free(tunnel_get.param_data);
+ if (tunnel_get.ret_data!= NULL)
+ free(tunnel_get.ret_data);
+ break;
+ }
+ default:
+ ALOGE("%s: Invalid plugin message type: %d", __func__, val);
+ ret = -EINVAL;
+ }
+
+ if(ret == 0) {
+ ret = ext_hw_plugin_dword_to_string(rbuf_dptr, rbuf_dlen, &rparms);
+ if (ret < 0) {
+ ALOGE("%s: Failed to convert param info for MSG_TYPE %d", __func__, val);
+ goto done_get_param;
+ }
+ ret = 0;
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_RESULT, ret);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_DATA, rparms);
+ }
+
+done_get_param:
+ if(ret) {
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_RESULT, ret);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_DATA, "");
+ }
+ if(rbuf_dptr!= NULL)
+ free(rbuf_dptr);
+ if(rparms!= NULL)
+ free(rparms);
+
+ ALOGI("%s: exit with code(%d)", __func__, ret);
+ if(kv_pairs != NULL)
+ free(kv_pairs);
+ if(value != NULL)
+ free(value);
+ return ret;
+}
+
+int audio_extn_ext_hw_plugin_set_mic_mute(void *plugin, bool mute)
+{
+ struct ext_hw_plugin_data *my_plugin = NULL;
+ audio_hal_plugin_codec_set_pp_mute_t pp_mute;
+ int ret = 0;
+
+ ALOGD("%s: received set mic mute (%d)", __func__, mute);
+
+ if (plugin == NULL) {
+ ALOGE("[%s] received null pointer",__func__);
+ return -EINVAL;
+ }
+
+ my_plugin = (struct ext_hw_plugin_data *)plugin;
+ if (!my_plugin->audio_hal_plugin_send_msg) {
+ ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__);
+ return -EINVAL;
+ }
+
+ my_plugin->mic_mute = mute;
+
+ /* Set mic mute is currently supported only for HFP call use case. */
+ if (my_plugin->usecase_ref_count[AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL]) {
+ pp_mute.snd_dev= my_plugin->in_snd_dev[AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL];
+ pp_mute.usecase = AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL;
+ pp_mute.ch_mask = AUDIO_CHANNEL_IN_ALL;
+ pp_mute.flag = mute;
+
+ ALOGV("%s: sending codec pp mute msg to HAL plugin driver, %d, %d, %x, %d",
+ __func__, (int)pp_mute.usecase, (int)pp_mute.snd_dev,
+ (int)pp_mute.ch_mask, (int)pp_mute.flag);
+ ret = my_plugin->audio_hal_plugin_send_msg(
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE, &pp_mute,
+ sizeof(pp_mute));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp mute err: %d", __func__, ret);
+ }
+ }
+
+ return ret;
+}
+
+int audio_extn_ext_hw_plugin_get_mic_mute(void *plugin, bool *mute)
+{
+ struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin;
+
+ if (my_plugin == NULL || mute == NULL) {
+ ALOGE("[%s] received null pointer", __func__);
+ return -EINVAL;
+ }
+
+ *mute = my_plugin->mic_mute;
+ ALOGD("%s: received get mic mute (%d)", __func__, *mute);
+
+ return 0;
+}
+
+int audio_extn_ext_hw_plugin_set_audio_gain(void *plugin,
+ struct audio_usecase *usecase, uint32_t gain)
+{
+ int32_t ret = 0;
+ struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin;
+ audio_hal_plugin_codec_set_pp_vol_t pp_vol;
+
+ if ((my_plugin == NULL) || (usecase == NULL)) {
+ ALOGE("%s: NULL input pointer", __func__);
+ return -EINVAL;
+ }
+
+ if (!my_plugin->audio_hal_plugin_send_msg) {
+ ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__);
+ return -EINVAL;
+ }
+
+ memset(&pp_vol, 0, sizeof(pp_vol));
+
+ ret = ext_hw_plugin_check_plugin_usecase(usecase->id, &pp_vol.usecase);
+ if (ret) {
+ ALOGI("%s: Set audio gain skipped for audio usecase %d",
+ __func__, usecase->id);
+ return 0;
+ }
+
+#if 0
+ /* Skip active usecase check and continue vol set to plugin
+ * to allow volume cached per usecase in plugin.
+ */
+ if (!my_plugin->usecase_ref_count[pp_vol.usecase]) {
+ ALOGV("%s: Plugin usecase %d is not enabled",
+ __func__, pp_vol.usecase);
+ return 0;
+ }
+
+ if (my_plugin->out_snd_dev[pp_vol.usecase]) {
+ pp_vol.snd_dev = my_plugin->out_snd_dev[pp_vol.usecase];
+ pp_vol.ch_mask = AUDIO_CHANNEL_OUT_ALL;
+ } else if (my_plugin->in_snd_dev[pp_vol.usecase]) {
+ pp_vol.snd_dev = my_plugin->in_snd_dev[pp_vol.usecase];
+ pp_vol.ch_mask = AUDIO_CHANNEL_IN_ALL;
+ } else {
+ ALOGE("%s: No valid snd_device found for usecase %d",
+ __func__, pp_vol.usecase);
+ return -EINVAL;
+ }
+#endif
+
+ /* NOTE: Use in/out snd device from usecase to decide
+ * which direction pp_volume should apply.
+ */
+ if (usecase->out_snd_device != SND_DEVICE_NONE) {
+ pp_vol.snd_dev = usecase->out_snd_device;
+ pp_vol.ch_mask = AUDIO_CHANNEL_OUT_ALL;
+ } else if (usecase->in_snd_device != SND_DEVICE_NONE) {
+ pp_vol.snd_dev = usecase->in_snd_device;
+ pp_vol.ch_mask = AUDIO_CHANNEL_IN_ALL;
+ } else {
+ ALOGE("%s: No valid snd_device found for usecase %d",
+ __func__, pp_vol.usecase);
+ return -EINVAL;
+ }
+
+ pp_vol.gain = gain;
+
+ ALOGD("%s: Sending codec pp vol msg to HAL plugin driver, %d, %d, %d, %d",
+ __func__, (int)pp_vol.usecase, (int)pp_vol.snd_dev,
+ (int)pp_vol.ch_mask, (int)pp_vol.gain);
+ ret = my_plugin->audio_hal_plugin_send_msg(
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME,
+ &pp_vol, sizeof(pp_vol));
+ if (ret) {
+ ALOGE("%s: Failed to set plugin pp vol err: %d", __func__, ret);
+ }
+ return ret;
+}
+#endif /* EXT_HW_PLUGIN_ENABLED */
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index 24facea..02561ba 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -166,6 +166,7 @@
int32_t pcm_dev_rx_id, pcm_dev_tx_id;
ALOGD("%s: enter", __func__);
+ fmmod.is_fm_running = true;
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
@@ -220,9 +221,6 @@
pcm_start(fmmod.fm_pcm_rx);
pcm_start(fmmod.fm_pcm_tx);
- fmmod.is_fm_running = true;
- fm_set_volume(adev, fmmod.fm_volume, false);
-
ALOGD("%s: exit: status(%d)", __func__, ret);
return 0;
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index a98d5e4..26ea72c 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -38,6 +38,7 @@
#include "platform_api.h"
#include <stdlib.h>
#include <cutils/str_parms.h>
+#include "audio_extn.h"
#ifdef DYNAMIC_LOG_ENABLED
#include <log_xml_parser.h>
@@ -55,6 +56,8 @@
#define HFP_RX_VOLUME "SEC AUXPCM LOOPBACK Volume"
#elif defined PLATFORM_MSM8996
#define HFP_RX_VOLUME "PRI AUXPCM LOOPBACK Volume"
+#elif defined PLATFORM_AUTO
+#define HFP_RX_VOLUME "Playback 36 Volume"
#elif defined (PLATFORM_MSM8998) || defined (PLATFORM_MSMFALCON) || defined (PLATFORM_SDM845) || defined (PLATFORM_SDM710) || defined (PLATFORM_QCS605) || defined (PLATFORM_MSMNILE) || defined (PLATFORM_MSMSTEPPE) || defined (PLATFORM_TRINKET)
#define HFP_RX_VOLUME "SLIMBUS_7 LOOPBACK Volume"
#else
@@ -163,6 +166,12 @@
select_devices(adev, hfpmod.ucid);
+ if ((uc_info->out_snd_device != SND_DEVICE_NONE) ||
+ (uc_info->in_snd_device != SND_DEVICE_NONE)) {
+ if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
+ ALOGE("%s: failed to start ext hw plugin", __func__);
+ }
+
pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
pcm_dev_asm_rx_id = hfpmod.hfp_pcm_dev_id;
@@ -280,6 +289,12 @@
return -EINVAL;
}
+ if ((uc_info->out_snd_device != SND_DEVICE_NONE) ||
+ (uc_info->in_snd_device != SND_DEVICE_NONE)) {
+ if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
+ ALOGE("%s: failed to stop ext hw plugin", __func__);
+ }
+
/* 2. Disable echo reference while stopping hfp */
platform_set_echo_reference(adev, false, uc_info->devices);
diff --git a/hal/audio_hal_plugin.h b/hal/audio_hal_plugin.h
new file mode 100644
index 0000000..9b20d3c
--- /dev/null
+++ b/hal/audio_hal_plugin.h
@@ -0,0 +1,375 @@
+/* Copyright (c) 2014-2015, 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef AUDIO_HAL_PLUGIN_H
+#define AUDIO_HAL_PLUGIN_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <audio_hw.h>
+
+#define AUDIO_HAL_PLUGIN_EOK (0)
+#define AUDIO_HAL_PLUGIN_EFAIL (-1) /**< Undefined error */
+#define AUDIO_HAL_PLUGIN_ENOMEM (-2) /**< Out of memory */
+#define AUDIO_HAL_PLUGIN_EINVAL (-3) /**< Invalid argument */
+#define AUDIO_HAL_PLUGIN_EBUSY (-4) /**< Plugin driver is busy */
+#define AUDIO_HAL_PLUGIN_ENODEV (-5) /**< No device */
+#define AUDIO_HAL_PLUGIN_EALREADY (-6) /**< Already done */
+
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE "ext_hw_plugin_msg_type"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC "ext_hw_plugin_usecase"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_SND_DEVICE "ext_hw_plugin_snd_device"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_DIRECTION "ext_hw_plugin_direction"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK "ext_hw_plugin_channel_mask"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GAIN "ext_hw_plugin_gain"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MUTE_FLAG "ext_hw_plugin_mute_flag"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_FADE "ext_hw_plugin_fade"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BALANCE "ext_hw_plugin_balance"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE "ext_hw_plugin_bmt_filter_type"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FLAG "ext_hw_plugin_bmt_flag"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_VAL "ext_hw_plugin_bmt_value"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_FLAG "ext_hw_plugin_eq_flag"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_ID "ext_hw_plugin_eq_id"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS "ext_hw_plugin_eq_num_bands"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_BAND_DATA "ext_hw_plugin_eq_band_data"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE "ext_hw_plugin_tunnel_size"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA "ext_hw_plugin_tunnel_data"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_RESULT "ext_hw_plugin_getparam_result"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_DATA "ext_hw_plugin_getparam_data"
+#define AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_GET_SIZE "ext_hw_plugin_tunnel_get_size"
+/**
+ * Type of audio hal plug-in messages
+ */
+typedef enum
+{
+ AUDIO_HAL_PLUGIN_MSG_INVALID = 0,
+ AUDIO_HAL_PLUGIN_MSG_CODEC_ENABLE, /**< setup codec routing path */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_DISABLE, /**< tear down routing path */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME, /**< set volume */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE, /**< mute/unmute control */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_FADE, /**< fade out control */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BALANCE, /**< left/right balance control */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BMT, /**< base/mid/treble control */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ, /**< EQ control */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD, /**< pass through cmds */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_VOLUME, /**< get volume params */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_FADE, /**< get fade params */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BALANCE, /**< get balance params */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BMT, /**< get bmt params */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ, /**< get EQ params */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS, /**< get EQ subbands params */
+ AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD, /**< pass through get cmds */
+ AUDIO_HAL_PLUGIN_MSG_MAX
+} audio_hal_plugin_msg_type_t;
+
+/**
+ * Type of audio hal plug-in use cases
+ */
+typedef enum
+{
+ AUDIO_HAL_PLUGIN_USECASE_INVALID = -1,
+ AUDIO_HAL_PLUGIN_USECASE_DEFAULT_PLAYBACK = 0,
+ AUDIO_HAL_PLUGIN_USECASE_DEFAULT_CAPTURE,
+ AUDIO_HAL_PLUGIN_USECASE_DRIVER_SIDE_PLAYBACK,
+ AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL,
+ AUDIO_HAL_PLUGIN_USECASE_CS_VOICE_CALL,
+ AUDIO_HAL_PLUGIN_USECASE_FM_TUNER,
+ AUDIO_HAL_PLUGIN_USECASE_ICC,
+ AUDIO_HAL_PLUGIN_USECASE_EC_CAPTURE,
+ AUDIO_HAL_PLUGIN_USECASE_EC_REF_CAPTURE,
+ AUDIO_HAL_PLUGIN_USECASE_ANC,
+ AUDIO_HAL_PLUGIN_USECASE_LINE_IN_PASSTHROUGH,
+ AUDIO_HAL_PLUGIN_USECASE_HDMI_IN_PASSTHROUGH,
+ AUDIO_HAL_PLUGIN_USECASE_PHONE_PLAYBACK,
+ AUDIO_HAL_PLUGIN_USECASE_MAX
+} audio_hal_plugin_usecase_type_t;
+
+/**
+ * Type of audio hal plug-in direction used in set_param
+ */
+typedef enum
+{
+ AUDIO_HAL_PLUGIN_DIRECTION_INVALID = -1,
+ AUDIO_HAL_PLUGIN_DIRECTION_PLAYBACK = 0,
+ AUDIO_HAL_PLUGIN_DIRECTION_CAPTURE,
+ AUDIO_HAL_PLUGIN_DIRECTION_MAX
+} audio_hal_plugin_direction_type_t;
+
+/**
+ * Type of query status mask
+ */
+#define QUERY_VALUE_VALID (0x0)
+#define QUERY_VALUE_NOT_SUPPORTED (0x1)
+#define QUERY_VALUE_NOT_SET (0x2)
+
+/**
+ * Type of signed 32-bit bounded value used in get_param
+ */
+typedef struct audio_hal_plugin_bint32
+{
+ uint32_t query_status_mask; /**< status of returned actual value */
+ int32_t value; /**< actual value */
+ int32_t min; /**< minimum for value */
+ int32_t max; /**< maximum for value */
+} audio_hal_plugin_bint32_t;
+
+/**
+ * Type of unsigned 32-bit bounded value used in get_param
+ */
+typedef struct audio_hal_plugin_buint32
+{
+ uint32_t query_status_mask; /**< status of returned actual value */
+ uint32_t value; /**< actual value */
+ uint32_t min; /**< minimum for value */
+ uint32_t max; /**< maximum for value */
+} audio_hal_plugin_buint32_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_ENABLE message
+ */
+typedef struct audio_hal_plugin_codec_enable
+{
+ snd_device_t snd_dev; /**< Requested endpoint device to be enabled. @enum: SND_DEVICE_XXX */
+ audio_hal_plugin_usecase_type_t usecase;
+ /**< Requested use case. @enum: AUDIO_HAL_PLUGIN_USECASE_XXX */
+ uint32_t sample_rate; /**< Requested sample rate for the endpoint device */
+ uint32_t bit_width; /**< Requested bit width per sample for the endpoint device */
+ uint32_t num_chs; /**< Requested number of channels for the endpoint device */
+} audio_hal_plugin_codec_enable_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_DISABLE message
+ */
+typedef struct audio_hal_plugin_codec_disable
+{
+ snd_device_t snd_dev; /**< Requested the endpoint device to be disabled */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+} audio_hal_plugin_codec_disable_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME message
+ */
+typedef struct audio_hal_plugin_codec_set_pp_vol
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_channel_mask_t ch_mask; /**< Requested audio channel mask */
+ uint32_t gain; /**< The requested volume setting. */
+} audio_hal_plugin_codec_set_pp_vol_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE message
+ */
+typedef struct audio_hal_plugin_codec_set_pp_mute
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_channel_mask_t ch_mask; /**< Requested audio channel mask */
+ bool flag; /**< Enable/Disable mute flag. 1: mute, 0: unmute */
+} audio_hal_plugin_codec_set_pp_mute_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_FADE message
+ */
+typedef struct audio_hal_plugin_codec_set_pp_fade
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ int32_t fade; /**< The requested fade configuration. */
+} audio_hal_plugin_codec_set_pp_fade_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BALANCE message
+ */
+typedef struct audio_hal_plugin_codec_set_pp_balance
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ int32_t balance; /**< The requested balance configuration. */
+} audio_hal_plugin_codec_set_pp_balance_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BMT message
+ */
+typedef enum
+{
+ AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID = 0,
+ AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_BASS,
+ AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_MID,
+ AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_TREBLE,
+ AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_MAX
+} audio_hal_plugin_codec_pp_filter_type_t;
+
+typedef struct audio_hal_plugin_codec_set_pp_bmt
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_hal_plugin_codec_pp_filter_type_t filter_type; /**< Requested filter type */
+ bool enable_flag; /**< Enable flag. 0 - Disable, 1 - Enable */
+ int32_t value; /**< Requested value to be set */
+} audio_hal_plugin_codec_set_pp_bmt_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ message
+ */
+typedef struct audio_hal_plugin_codec_pp_eq_subband
+{
+ uint32_t band_idx; /**< Band index. Supported value: 0 to (num_bands - 1) */
+ uint32_t center_freq; /**< Filter band center frequency in millihertz */
+ int32_t band_level; /**< Filter band gain in millibels */
+} audio_hal_plugin_codec_pp_eq_subband_t;
+
+typedef struct audio_hal_plugin_codec_set_pp_eq
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ bool enable_flag; /**< Enable flag. 0 - Disable, 1 - Enable */
+ int32_t preset_id; /**< Specify to use either pre-defined preset EQ or
+ user-customized equalizers:
+ -1 - custom equalizer speficied through 'bands' struct
+ 0 to N - pre-defined preset EQ index: ROCK/JAZZ/POP, etc */
+ uint32_t num_bands; /**< Number of EQ subbands when a custom preset_id is selected */
+ audio_hal_plugin_codec_pp_eq_subband_t *bands; /**< Equalizer sub-band struct list */
+} audio_hal_plugin_codec_set_pp_eq_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_VOLUME message
+ */
+typedef struct audio_hal_plugin_codec_get_pp_vol
+{
+ snd_device_t snd_dev; /**< Requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_channel_mask_t ch_mask; /**< Requested audio channel mask */
+ audio_hal_plugin_buint32_t ret_gain; /**< Returned volume range and value */
+} audio_hal_plugin_codec_get_pp_vol_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_FADE message
+ */
+typedef struct audio_hal_plugin_codec_get_pp_fade
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_hal_plugin_bint32_t ret_fade; /**< Returned fade range and value. */
+} audio_hal_plugin_codec_get_pp_fade_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BALANCE message
+ */
+typedef struct audio_hal_plugin_codec_get_pp_balance
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_hal_plugin_bint32_t ret_balance; /**< Returned balance range and value. */
+} audio_hal_plugin_codec_get_pp_balance_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BMT message
+ */
+typedef struct audio_hal_plugin_codec_get_pp_bmt
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_hal_plugin_codec_pp_filter_type_t filter_type; /**< Requested filter type */
+ audio_hal_plugin_bint32_t ret_value; /**< Returned range and value */
+} audio_hal_plugin_codec_get_pp_bmt_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ message
+ */
+typedef struct audio_hal_plugin_codec_get_pp_eq
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ audio_hal_plugin_bint32_t ret_preset_id; /**< Returned preset id
+ -1 - custom equalizer speficied through 'bands' struct
+ 0 to N - pre-defined preset EQ index: ROCK/JAZZ/POP, etc */
+ uint32_t ret_num_bands; /**< Returned number of EQ subbands supported
+ when a custom preset_id is selected */
+} audio_hal_plugin_codec_get_pp_eq_t;
+
+/**
+ * Eq_subband struct used in the following payload
+ */
+typedef struct audio_hal_plugin_pp_eq_subband_binfo
+{
+ audio_hal_plugin_buint32_t ret_center_freq; /**< Returned band center frequency range
+ and value in millihertz */
+ audio_hal_plugin_bint32_t ret_band_level; /**< Returned band gain range and value in millibels */
+} audio_hal_plugin_pp_eq_subband_binfo_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS message
+ */
+typedef struct audio_hal_plugin_codec_get_pp_eq_subbands
+{
+ snd_device_t snd_dev; /**< The requested endpoint device */
+ audio_hal_plugin_usecase_type_t usecase; /**< Requested use case */
+ uint32_t num_bands; /**< number of EQ subbands supported for custom eq
+ returned from get_pp_eq query */
+ audio_hal_plugin_pp_eq_subband_binfo_t *ret_bands; /**< Returned subband info list */
+} audio_hal_plugin_codec_get_pp_eq_subbands_t;
+
+/**
+ * Payload of AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD message
+ */
+typedef struct audio_hal_plugin_codec_tunnel_get
+{
+ int32_t *param_data; /**< Request param data from client */
+ uint32_t param_size; /**< Request 32-bit data size from client */
+ uint32_t size_to_get; /**< Expected 32-bit data size to get from cleint */
+ int32_t *ret_data; /**< Returned data */
+ uint32_t ret_size; /**< Returned 32-bit data size */
+} audio_hal_plugin_codec_tunnel_get_t;
+
+/**
+ * Initialize the audio hal plug-in module and underlying hw driver
+ * One time call at audio hal boot up time
+ */
+int32_t audio_hal_plugin_init (void);
+
+/**
+ * De-Initialize the audio hal plug-in module and underlying hw driver
+ * One time call when audio hal get unloaded from system
+ */
+int32_t audio_hal_plugin_deinit (void);
+
+/**
+ * Function to invoke the underlying HW driver realizing the functionality for a given use case.
+ */
+int32_t audio_hal_plugin_send_msg (
+ audio_hal_plugin_msg_type_t msg,
+ void * payload, uint32_t payload_size);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 78f2560..d35ff0d 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -966,6 +966,7 @@
snd_device_t snd_device;
char mixer_path[MIXER_PATH_MAX_LENGTH];
struct stream_out *out = NULL;
+ int ret = 0;
if (usecase == NULL)
return -EINVAL;
@@ -995,7 +996,14 @@
strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
platform_add_backend_name(mixer_path, snd_device, usecase);
ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
- audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+ ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+ if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
+ struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
+ if (parms) {
+ audio_extn_fm_set_parameters(adev, parms);
+ str_parms_destroy(parms);
+ }
+ }
ALOGV("%s: exit", __func__);
return 0;
}
@@ -1477,11 +1485,6 @@
usecase->stream.out->volume_l,
usecase->stream.out->volume_r);
}
- if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
- struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
- if (parms)
- audio_extn_fm_set_parameters(adev, parms);
- }
}
}
}
@@ -2419,6 +2422,11 @@
return -EINVAL;
}
+ if (uc_info->in_snd_device != SND_DEVICE_NONE) {
+ if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
+ ALOGE("%s: failed to stop ext hw plugin", __func__);
+ }
+
/* Close in-call recording streams */
voice_check_and_stop_incall_rec_usecase(adev, in);
@@ -2514,6 +2522,11 @@
adev->perf_lock_opts_size);
select_devices(adev, in->usecase);
+ if (uc_info->in_snd_device != SND_DEVICE_NONE) {
+ if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
+ ALOGE("%s: failed to start ext hw plugin", __func__);
+ }
+
if (audio_extn_cin_attached_usecase(in->usecase)) {
ret = audio_extn_cin_start_input_stream(in);
if (ret)
@@ -2934,6 +2947,11 @@
return -EINVAL;
}
+ if (uc_info->out_snd_device != SND_DEVICE_NONE) {
+ if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
+ ALOGE("%s: failed to stop ext hw plugin", __func__);
+ }
+
if (is_offload_usecase(out->usecase) &&
!(audio_extn_passthru_is_passthrough_stream(out))) {
if (adev->visualizer_stop_output != NULL)
@@ -3122,6 +3140,11 @@
out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
voice_set_device_mute_flag(adev, true);
+ if (uc_info->out_snd_device != SND_DEVICE_NONE) {
+ if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
+ ALOGE("%s: failed to start ext hw plugin", __func__);
+ }
+
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
__func__, adev->snd_card, out->pcm_device_id, out->config.format);
@@ -5846,7 +5869,7 @@
ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
return ret;
}
- position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
+ position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
return 0;
}
@@ -6950,6 +6973,8 @@
pthread_mutex_lock(&adev->lock);
ALOGD("%s state %d\n", __func__, state);
ret = voice_set_mic_mute((struct audio_device *)dev, state);
+ if (adev->ext_hw_plugin)
+ ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
pthread_mutex_unlock(&adev->lock);
return ret;
@@ -7483,6 +7508,8 @@
free(adev->device_cfg_params);
adev->device_cfg_params = NULL;
}
+ if(adev->ext_hw_plugin)
+ audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
free(device);
adev = NULL;
}
@@ -7736,6 +7763,8 @@
adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
}
+ adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
+
if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
if (adev->visualizer_lib == NULL) {
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 202e09a..c13ca56 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -536,6 +536,7 @@
struct audio_device_config_param *device_cfg_params;
unsigned int interactive_usecase_state;
bool dp_allowed_for_voice;
+ void *ext_hw_plugin;
};
int select_devices(struct audio_device *adev,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index b8554f5..bae45b3 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -2561,6 +2561,26 @@
my_data->current_backend_cfg[HDMI_TX_BACKEND].channels_mixer_ctl =
strdup("QUAT_MI2S_TX Channels");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("HDMI_RX Bit Format");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("HDMI_RX SampleRate");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].channels_mixer_ctl =
+ strdup("HDMI_RX Channels");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("Display Port RX Bit Format");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("Display Port RX SampleRate");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels_mixer_ctl =
+ strdup("Display Port RX Channels");
+
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("USB_AUDIO_RX Format");
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("USB_AUDIO_RX SampleRate");
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].channels_mixer_ctl =
+ strdup("USB_AUDIO_RX Channels");
+
for (idx = 0; idx < MAX_CODEC_BACKENDS; idx++) {
if (my_data->current_backend_cfg[idx].bitwidth_mixer_ctl) {
ctl = mixer_get_ctl_by_name(adev->mixer,
@@ -2620,26 +2640,6 @@
}
}
- my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
- strdup("HDMI_RX Bit Format");
- my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
- strdup("HDMI_RX SampleRate");
- my_data->current_backend_cfg[HDMI_RX_BACKEND].channels_mixer_ctl =
- strdup("HDMI_RX Channels");
- my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bitwidth_mixer_ctl =
- strdup("Display Port RX Bit Format");
- my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].samplerate_mixer_ctl =
- strdup("Display Port RX SampleRate");
- my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels_mixer_ctl =
- strdup("Display Port RX Channels");
-
- my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
- strdup("USB_AUDIO_RX Format");
- my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
- strdup("USB_AUDIO_RX SampleRate");
- my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].channels_mixer_ctl =
- strdup("USB_AUDIO_RX Channels");
-
if (property_get_bool("vendor.audio.apptype.multirec.enabled", false))
my_data->use_generic_handset = true;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 5fbff5f..23953e6 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -492,6 +492,9 @@
#elif PLATFORM_BEAR_FAMILY
#define HFP_SCO_RX 17
#define HFP_ASM_RX_TX 18
+#elif PLATFORM_AUTO
+#define HFP_SCO_RX 36
+#define HFP_ASM_RX_TX 29
#else
#define HFP_SCO_RX 23
#define HFP_ASM_RX_TX 24