[automerger skipped] DO NOT MERGE - Merge PPRL.190205.001 into master am: c661b01014 -s ours am: cb178c4754 -s ours
am: 953646cfe7 -s ours
am skip reason: subject contains skip directive
Change-Id: I4d8380d72eb1b4e00925ce12779dc40609dbaba0
diff --git a/Android.mk b/Android.mk
index 41109b0..34b228a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,6 +1,6 @@
# TODO: Find a better way to separate build configs for ADP vs non-ADP devices
ifneq ($(TARGET_BOARD_AUTO),true)
- ifneq ($(filter msm8960 msm8226 msm8x26 msm8x84 msm8084 msm8992 msm8994 msm8996 msm8909 msm8952 msm8998 sdm845 sdm710 sm8150,$(TARGET_BOARD_PLATFORM)),)
+ ifneq ($(filter msm8960 msm8226 msm8x26 msm8x84 msm8084 msm8992 msm8994 msm8996 msm8909 msm8952 msm8998 sdm845 sdm710 msmnile,$(TARGET_BOARD_PLATFORM)),)
MY_LOCAL_PATH := $(call my-dir)
diff --git a/hal/Android.mk b/hal/Android.mk
index 05455b5..3bdcf12 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -10,7 +10,7 @@
ifneq ($(filter msm8960,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="2"
endif
-ifneq ($(filter msm8974 msm8226 msm8084 msm8992 msm8994 msm8996 msm8998 sdm845 sdm710 sm8150,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8974 msm8226 msm8084 msm8992 msm8994 msm8996 msm8998 sdm845 sdm710 msmnile,$(TARGET_BOARD_PLATFORM)),)
# B-family platform uses msm8974 code base
AUDIO_PLATFORM = msm8974
ifneq ($(filter msm8974,$(TARGET_BOARD_PLATFORM)),)
@@ -62,7 +62,7 @@
LOCAL_CFLAGS += -DINCALL_STEREO_CAPTURE_ENABLED
MULTIPLE_HW_VARIANTS_ENABLED := true
endif
-ifneq ($(filter sm8150,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msmnile,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_SM8150
LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="4"
LOCAL_CFLAGS += -DINCALL_MUSIC_ENABLED
@@ -198,7 +198,6 @@
LOCAL_SRC_FILES += audio_extn/sndmonitor.c
endif
-
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_USB_SERVICE_INTERVAL)), true)
LOCAL_CFLAGS += -DUSB_SERVICE_INTERVAL_ENABLED
endif
@@ -216,6 +215,10 @@
LOCAL_CFLAGS += -DBG_CODEC_CAL
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DYNAMIC_ECNS)),true)
+ LOCAL_CFLAGS += -DDYNAMIC_ECNS_ENABLED
+endif
+
LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhwbinder libutils android.hardware.power@1.2 liblog
LOCAL_SRC_FILES += audio_perf.cpp
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 671fe59..43b3da9 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -34,6 +34,7 @@
#ifdef A2DP_OFFLOAD_ENABLED
#define BT_IPC_LIB_NAME "libbthost_if.so"
+#define BTAUDIO_OFFLOAD_LIB_NAME "btaudio_offload_if.so"
// Media format definitions
#define ENC_MEDIA_FMT_AAC 0x00010DA6
@@ -78,6 +79,7 @@
// System properties used for A2DP Offload
#define SYSPROP_A2DP_OFFLOAD_SUPPORTED "ro.bluetooth.a2dp_offload.supported"
#define SYSPROP_A2DP_OFFLOAD_DISABLED "persist.bluetooth.a2dp_offload.disabled"
+#define SYSPROP_BLUETOOTH_AUDIO_HAL_ENABLED "persist.vendor.bluetooth.bluetooth_audio_hal.enabled"
#define SYSPROP_A2DP_CODEC_LATENCIES "vendor.audio.a2dp.codec.latency"
// Default encoder bit width
@@ -141,6 +143,7 @@
enc_codec_t *codec_type);
typedef int (*audio_check_a2dp_ready_t)(void);
typedef int (*audio_is_scrambling_enabled_t)(void);
+typedef uint16_t (*audio_get_a2dp_sink_latency_t)(void);
enum A2DP_STATE {
A2DP_STATE_CONNECTED,
@@ -221,6 +224,8 @@
audio_check_a2dp_ready_t audio_check_a2dp_ready;
/* Check if scrambling is enabled on BTSoC */
audio_is_scrambling_enabled_t audio_is_scrambling_enabled;
+ /* Get sink latency from Bluetooth stack */
+ audio_get_a2dp_sink_latency_t audio_get_a2dp_sink_latency;
/* Internal A2DP state identifier */
enum A2DP_STATE bt_state;
/* A2DP codec type configured */
@@ -673,8 +678,9 @@
static int open_a2dp_output()
{
int ret = 0;
-
ALOGD("%s: Open A2DP output start", __func__);
+ bool hal_v2_enabled =
+ property_get_bool(SYSPROP_BLUETOOTH_AUDIO_HAL_ENABLED, false);
if (a2dp.bt_state != A2DP_STATE_DISCONNECTED) {
ALOGD("%s: Called A2DP open with improper state, Ignoring request state %d",
@@ -683,9 +689,13 @@
}
if (a2dp.bt_lib_handle == NULL) {
- ALOGD("%s: Requesting for Bluetooth IPC lib handle", __func__);
- a2dp.bt_lib_handle = dlopen(BT_IPC_LIB_NAME, RTLD_NOW);
-
+ ALOGD("%s: Requesting for Bluetooth IPC lib handle [%s]", __func__,
+ hal_v2_enabled ? BTAUDIO_OFFLOAD_LIB_NAME : BT_IPC_LIB_NAME);
+ if (hal_v2_enabled) {
+ a2dp.bt_lib_handle = dlopen(BTAUDIO_OFFLOAD_LIB_NAME, RTLD_NOW);
+ } else {
+ a2dp.bt_lib_handle = dlopen(BT_IPC_LIB_NAME, RTLD_NOW);
+ }
if (a2dp.bt_lib_handle == NULL) {
ret = -errno;
ALOGE("%s: DLOPEN failed for %s errno %d strerror %s", __func__,
@@ -713,6 +723,8 @@
dlsym(a2dp.bt_lib_handle,"audio_check_a2dp_ready");
a2dp.audio_is_scrambling_enabled = (audio_is_scrambling_enabled_t)
dlsym(a2dp.bt_lib_handle,"audio_is_scrambling_enabled");
+ a2dp.audio_get_a2dp_sink_latency = (audio_get_a2dp_sink_latency_t)
+ dlsym(a2dp.bt_lib_handle,"audio_get_a2dp_sink_latency");
}
}
@@ -1714,7 +1726,7 @@
uint32_t audio_extn_a2dp_get_encoder_latency()
{
- uint32_t latency = 0;
+ uint32_t latency_ms = 0;
int avsync_runtime_prop = 0;
int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0,
aac_offset = 0, ldac_offset = 0;
@@ -1731,36 +1743,41 @@
}
}
+ uint32_t slatency_ms = 0;
+ if (a2dp.audio_get_a2dp_sink_latency && a2dp.bt_state != A2DP_STATE_DISCONNECTED) {
+ slatency_ms = a2dp.audio_get_a2dp_sink_latency();
+ }
+
switch (a2dp.bt_encoder_format) {
case ENC_CODEC_TYPE_SBC:
- latency = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
- latency += DEFAULT_SINK_LATENCY_SBC;
+ latency_ms = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
+ latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_SBC : slatency_ms;
break;
case ENC_CODEC_TYPE_APTX:
- latency = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
- latency += DEFAULT_SINK_LATENCY_APTX;
+ latency_ms = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
+ latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_APTX : slatency_ms;
break;
case ENC_CODEC_TYPE_APTX_HD:
- latency = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
- latency += DEFAULT_SINK_LATENCY_APTX_HD;
+ latency_ms = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
+ latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_APTX_HD : slatency_ms;
break;
case ENC_CODEC_TYPE_AAC:
- latency = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
- latency += DEFAULT_SINK_LATENCY_AAC;
+ latency_ms = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
+ latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_AAC : slatency_ms;
break;
case ENC_CODEC_TYPE_LDAC:
- latency = (avsync_runtime_prop > 0) ? ldac_offset : ENCODER_LATENCY_LDAC;
- latency += DEFAULT_SINK_LATENCY_LDAC;
+ latency_ms = (avsync_runtime_prop > 0) ? ldac_offset : ENCODER_LATENCY_LDAC;
+ latency_ms += (slatency_ms == 0) ? DEFAULT_SINK_LATENCY_LDAC : slatency_ms;
break;
case ENC_CODEC_TYPE_PCM:
- latency = ENCODER_LATENCY_PCM;
- latency += DEFAULT_SINK_LATENCY_PCM;
+ latency_ms = ENCODER_LATENCY_PCM;
+ latency_ms += DEFAULT_SINK_LATENCY_PCM;
break;
default:
- latency = DEFAULT_ENCODER_LATENCY;
+ latency_ms = DEFAULT_ENCODER_LATENCY;
break;
}
- return latency;
+ return latency_ms;
}
int audio_extn_a2dp_get_parameters(struct str_parms *query,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 1c28b6b..54ea017 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -86,6 +86,7 @@
#define audio_extn_usb_alive(adev) (false)
#define audio_extn_usb_find_service_interval(m, p) ((m), (p), 0) /* fix unused warn */
#define audio_extn_usb_altset_for_service_interval(p, si, bw, sr, ch) (-1)
+#define audio_extn_usb_usbid() (NULL)
#else
void audio_extn_usb_init(void *adev);
void audio_extn_usb_deinit();
@@ -109,6 +110,7 @@
uint32_t *bit_width,
uint32_t *sample_rate,
uint32_t *channel_count);
+char *audio_extn_usb_usbid(void);
#endif
diff --git a/hal/audio_extn/maxxaudio.c b/hal/audio_extn/maxxaudio.c
index 2fd188d..69c4606 100644
--- a/hal/audio_extn/maxxaudio.c
+++ b/hal/audio_extn/maxxaudio.c
@@ -43,13 +43,15 @@
#define MA_QDSP_PARAM_INIT "maxxaudio_qdsp_initialize"
#define MA_QDSP_PARAM_DEINIT "maxxaudio_qdsp_uninitialize"
+#define MA_QDSP_IS_FEATURE_USED "maxxaudio_qdsp_is_feature_supported"
#define MA_QDSP_SET_LR_SWAP "maxxaudio_qdsp_set_lr_swap"
+#define MA_QDSP_SET_ORIENTATION "maxxaudio_qdsp_set_orientation"
#define MA_QDSP_SET_MODE "maxxaudio_qdsp_set_sound_mode"
#define MA_QDSP_SET_VOL "maxxaudio_qdsp_set_volume"
#define MA_QDSP_SET_VOLT "maxxaudio_qdsp_set_volume_table"
#define MA_QDSP_SET_PARAM "maxxaudio_qdsp_set_parameter"
-#define SUPPORT_DEV "Blackbird"
+#define SUPPORT_DEV "18d1:5033" // Blackbird usbid
#define SUPPORTED_USB 0x01
typedef unsigned int effective_scope_flag_t;
@@ -87,6 +89,8 @@
MA_CMD_VOL,
MA_CMD_SWAP_ENABLE,
MA_CMD_SWAP_DISABLE,
+ MA_CMD_ROTATE_ENABLE,
+ MA_CMD_ROTATE_DISABLE,
MA_CMD_SOFT_MUTE_ENABLE,
MA_CMD_SOFT_MUTE_DISABLE,
} ma_cmd_t;
@@ -120,9 +124,14 @@
typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t *);
+typedef bool (*ma_is_feature_used_t)(ma_audio_cal_handle_t, const char *);
+
typedef bool (*ma_set_lr_swap_t)(ma_audio_cal_handle_t,
const struct ma_audio_cal_settings *, bool);
+typedef bool (*ma_set_orientation_t)(ma_audio_cal_handle_t,
+ const struct ma_audio_cal_settings *, int);
+
typedef bool (*ma_set_sound_mode_t)(ma_audio_cal_handle_t,
const struct ma_audio_cal_settings *,
unsigned int);
@@ -144,11 +153,16 @@
pthread_mutex_t lock;
ma_param_init_t ma_param_init;
ma_param_deinit_t ma_param_deinit;
+ ma_is_feature_used_t ma_is_feature_used;
ma_set_lr_swap_t ma_set_lr_swap;
+ ma_set_orientation_t ma_set_orientation;
ma_set_sound_mode_t ma_set_sound_mode;
ma_set_volume_t ma_set_volume;
ma_set_volume_table_t ma_set_volume_table;
ma_set_param_t ma_set_param;
+ bool speaker_lr_swap;
+ bool orientation_used;
+ int dispaly_orientation;
};
ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL;
@@ -171,6 +185,13 @@
audio_cal_settings, swap);
}
+static bool ma_set_orientation_l(
+ const struct ma_audio_cal_settings *audio_cal_settings, int orientation)
+{
+ return my_data->ma_set_orientation(g_ma_audio_cal_handle,
+ audio_cal_settings, orientation);
+}
+
static bool ma_set_sound_mode_l(
const struct ma_audio_cal_settings *audio_cal_settings, int sound_mode)
{
@@ -211,8 +232,10 @@
(usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD)) &&
/* support devices */
((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
- (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE)))
- /* TODO: enable A2DP/USB when it is ready */
+ (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
+ (audio_is_usb_out_device(usecase->devices) &&
+ audio_extn_ma_supported_usb())))
+ /* TODO: enable A2DP when it is ready */
return true;
@@ -281,11 +304,14 @@
break;
case MA_CMD_SWAP_ENABLE:
- ret = ma_set_lr_swap_l(&ma_cal, true);
- if (ret)
- ALOGV("ma_set_lr_swap_l enable returned with success.");
- else
- ALOGE("ma_set_lr_swap_l enable returned with error.");
+ /* lr swap only enable for speaker path */
+ if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+ ret = ma_set_lr_swap_l(&ma_cal, true);
+ if (ret)
+ ALOGV("ma_set_lr_swap_l enable returned with success.");
+ else
+ ALOGE("ma_set_lr_swap_l enable returned with error.");
+ }
break;
case MA_CMD_SWAP_DISABLE:
@@ -296,6 +322,24 @@
ALOGE("ma_set_lr_swap_l disable returned with error.");
break;
+ case MA_CMD_ROTATE_ENABLE:
+ if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+ ret = ma_set_orientation_l(&ma_cal, my_data->dispaly_orientation);
+ if (ret)
+ ALOGV("ma_set_orientation_l %d returned with success.", my_data->dispaly_orientation);
+ else
+ ALOGE("ma_set_orientation_l %d returned with error.", my_data->dispaly_orientation);
+ }
+ break;
+
+ case MA_CMD_ROTATE_DISABLE:
+ ret = ma_set_orientation_l(&ma_cal, 0);
+ if (ret)
+ ALOGV("ma_set_orientation_l 0 returned with success.");
+ else
+ ALOGE("ma_set_orientation_l 0 returned with error.");
+ break;
+
case MA_CMD_SOFT_MUTE_ENABLE:
if (usecase->id == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) break;
@@ -351,20 +395,20 @@
static void ma_set_swap_l(struct audio_device *adev, bool enable)
{
- // do platform LR swap if it enables on Waves effect
- // but there is no Waves implementation
- if (!my_data) {
- platform_check_and_set_swap_lr_channels(adev, enable);
- ALOGV("%s: maxxaudio isn't initialized.", __func__);
- return;
- }
-
if (enable)
check_and_send_all_audio_cal(adev, MA_CMD_SWAP_ENABLE);
else
check_and_send_all_audio_cal(adev, MA_CMD_SWAP_DISABLE);
}
+static void ma_set_rotation_l(struct audio_device *adev, int orientation)
+{
+ if (orientation != 0)
+ check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_ENABLE);
+ else
+ check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_DISABLE);
+}
+
static void ma_support_usb(bool enable, int card)
{
char path[128];
@@ -374,7 +418,7 @@
char *idd;
if (enable) {
- ret = snprintf(path, sizeof(path), "/proc/asound/card%u/id", card);
+ ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid", card);
if (ret < 0) {
ALOGE("%s: failed on snprintf (%d) to path %s\n",
__func__, ret, path);
@@ -394,10 +438,10 @@
idd = strtok(id, "\n");
if (find_sup_dev(idd)) {
- ALOGV("%s: support device name is %s", __func__, id);
+ ALOGV("%s: support usbid is %s", __func__, id);
g_supported_dev |= SUPPORTED_USB;
} else
- ALOGV("%s: device %s isn't found from %s", __func__, id, SUPPORT_DEV);
+ ALOGV("%s: usbid %s isn't found from %s", __func__, id, SUPPORT_DEV);
} else {
g_supported_dev &= ~SUPPORTED_USB;
}
@@ -459,6 +503,18 @@
goto error;
}
+ my_data->ma_is_feature_used = (ma_is_feature_used_t)dlsym(my_data->waves_handle,
+ MA_QDSP_IS_FEATURE_USED);
+ if (!my_data->ma_is_feature_used) {
+ ALOGV("%s: dlsym error %s for ma_is_feature_used", __func__, dlerror());
+ }
+
+ my_data->ma_set_orientation = (ma_set_orientation_t)dlsym(my_data->waves_handle,
+ MA_QDSP_SET_ORIENTATION);
+ if (!my_data->ma_set_orientation) {
+ ALOGV("%s: dlsym error %s for ma_set_orientation", __func__, dlerror());
+ }
+
my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
MA_QDSP_SET_LR_SWAP);
if (!my_data->ma_set_lr_swap) {
@@ -556,6 +612,14 @@
ma_cur_state_table[i].active = false;
}
+ my_data->speaker_lr_swap = false;
+ my_data->orientation_used = false;
+ my_data->dispaly_orientation = 0;
+
+ if (g_ma_audio_cal_handle && my_data->ma_is_feature_used) {
+ my_data->orientation_used = my_data->ma_is_feature_used(g_ma_audio_cal_handle, "SET_ORIENTATION");
+ }
+
return;
error:
@@ -657,6 +721,19 @@
pthread_mutex_lock(&my_data->lock);
if (is_active()) {
+
+ if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (my_data->orientation_used)
+ ma_set_rotation_l(usecase->stream.out->dev, my_data->dispaly_orientation);
+ else
+ ma_set_swap_l(usecase->stream.out->dev, my_data->speaker_lr_swap);
+ } else {
+ if (my_data->orientation_used)
+ ma_set_rotation_l(usecase->stream.out->dev, 0);
+ else
+ ma_set_swap_l(usecase->stream.out->dev, false);
+ }
+
ALOGV("%s: send volume table === Start", __func__);
for (i = 0; i < STREAM_MAX_TYPES; i++)
ALOGV("%s: stream(%d) volume(%f) active(%s)", __func__, i,
@@ -686,16 +763,27 @@
// do LR swap and usb recognition
ret = str_parms_get_int(parms, "rotation", &val);
if (ret >= 0) {
+ if (!my_data) {
+ ALOGV("%s: maxxaudio isn't initialized.", __func__);
+ return;
+ }
+
switch (val) {
case 270:
- ma_set_swap_l(adev, true);
+ my_data->speaker_lr_swap = true;
break;
case 0:
case 90:
case 180:
- ma_set_swap_l(adev, false);
+ my_data->speaker_lr_swap = false;
break;
}
+ my_data->dispaly_orientation = val;
+
+ if (my_data->orientation_used)
+ ma_set_rotation_l(adev, my_data->dispaly_orientation);
+ else
+ ma_set_swap_l(adev, my_data->speaker_lr_swap);
}
// check connect status
diff --git a/hal/audio_extn/sndmonitor.c b/hal/audio_extn/sndmonitor.c
index 2e8fd43..85a8c94 100644
--- a/hal/audio_extn/sndmonitor.c
+++ b/hal/audio_extn/sndmonitor.c
@@ -194,7 +194,8 @@
if ((strncasecmp(card_id, "msm", 3) != 0) &&
(strncasecmp(card_id, "sdm", 3) != 0) &&
(strncasecmp(card_id, "sdc", 3) != 0) &&
- (strncasecmp(card_id, "apq", 3) != 0)) {
+ (strncasecmp(card_id, "apq", 3) != 0) &&
+ (strncasecmp(card_id, "sm8150", 6) != 0)) {
ALOGW("Skip over non-ADSP snd card %s", card_id);
continue;
}
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 71e1aed..b0b5049 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -43,6 +43,7 @@
#define SAMPLE_RATE_8000 8000
#define SAMPLE_RATE_11025 11025
#define DEFAULT_SERVICE_INTERVAL_US 1000
+#define USBID_SIZE 16
/* TODO: dynamically populate supported sample rates */
static uint32_t supported_sample_rates[] =
@@ -83,6 +84,7 @@
int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
int usb_sidetone_vol_min;
int usb_sidetone_vol_max;
+ char usbid[USBID_SIZE];
};
struct usb_module {
@@ -510,6 +512,48 @@
return ret;
}
+static int usb_get_usbid(struct usb_card_config *usb_card_info,
+ int card)
+{
+ int32_t fd=-1;
+ char path[128];
+ int ret = 0;
+
+ memset(usb_card_info->usbid, 0, sizeof(usb_card_info->usbid));
+
+ ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid",
+ card);
+
+ if (ret < 0) {
+ ALOGE("%s: failed on snprintf (%d) to path %s\n",
+ __func__, ret, path);
+ goto done;
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ALOGE("%s: error failed to open file %s error: %d\n",
+ __func__, path, errno);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (read(fd, usb_card_info->usbid, USBID_SIZE - 1) < 0) {
+ ALOGE("file read error\n");
+ ret = -EINVAL;
+ usb_card_info->usbid[0] = '\0';
+ goto done;
+ }
+
+ strtok(usb_card_info->usbid, "\n");
+
+done:
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+
static int usb_get_device_playback_config(struct usb_card_config *usb_card_info,
int card)
{
@@ -1082,6 +1126,10 @@
}
list_init(&usb_card_info->usb_device_conf_list);
if (usb_output_device(device)) {
+ if (usb_get_usbid(usb_card_info, card) < 0) {
+ ALOGE("parse card %d usbid fail", card);
+ }
+
if (!usb_get_device_playback_config(usb_card_info, card)){
usb_card_info->usb_card = card;
usb_card_info->usb_device_type = device;
@@ -1090,6 +1138,10 @@
goto exit;
}
} else if (usb_input_device(device)) {
+ if (usb_get_usbid(usb_card_info, card) < 0) {
+ ALOGE("parse card %d usbid fail", card);
+ }
+
if (!usb_get_device_capture_config(usb_card_info, card)) {
usb_card_info->usb_card = card;
usb_card_info->usb_device_type = device;
@@ -1251,6 +1303,22 @@
return 0;
}
+char *audio_extn_usb_usbid()
+{
+ struct usb_card_config *card_info;
+
+ if (usbmod == NULL)
+ return NULL;
+
+ if (list_empty(&usbmod->usb_card_conf_list))
+ return NULL;
+
+ card_info = node_to_item(list_head(&usbmod->usb_card_conf_list),\
+ struct usb_card_config, list);
+
+ return strdup(card_info->usbid);
+}
+
void audio_extn_usb_init(void *adev)
{
if (usbmod == NULL) {
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 73de0ab..3a1877b 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -281,6 +281,10 @@
usecase->out_snd_device,
out->sample_rate,
sample_rate);
+ } else if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ audio_extn_a2dp_get_sample_rate(sample_rate);
+ ALOGI("%s: Using sample rate %d for A2DP CoPP", __func__,
+ *sample_rate);
}
app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
@@ -577,7 +581,7 @@
}
/* Initialize snd card name specific ids and/or backends*/
- if (snd_card_info_init(platform_info_file, my_data,
+ if (platform_info_init(platform_info_file, my_data, false,
&acdb_set_parameters) < 0) {
ALOGE("Failed to find platform_info_file");
goto cleanup;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 731f444..24d726f 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -131,6 +131,26 @@
.avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
};
+struct pcm_config pcm_config_haptics_audio = {
+ .channels = 1,
+ .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
+ .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
+ .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
+ .stop_threshold = INT_MAX,
+ .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
+};
+
+struct pcm_config pcm_config_haptics = {
+ .channels = 1,
+ .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
+ .period_count = 2,
+ .format = PCM_FORMAT_S16_LE,
+ .stop_threshold = INT_MAX,
+ .avail_min = 0,
+};
+
static int af_period_multiplier = 4;
struct pcm_config pcm_config_rt = {
.channels = DEFAULT_CHANNEL_COUNT,
@@ -225,7 +245,7 @@
#define AFE_PROXY_CHANNEL_COUNT 2
#define AFE_PROXY_SAMPLING_RATE 48000
-#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
+#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
struct pcm_config pcm_config_afe_proxy_playback = {
@@ -239,7 +259,7 @@
.avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
};
-#define AFE_PROXY_RECORD_PERIOD_SIZE 768
+#define AFE_PROXY_RECORD_PERIOD_SIZE 256
#define AFE_PROXY_RECORD_PERIOD_COUNT 4
struct pcm_config pcm_config_afe_proxy_record = {
@@ -256,6 +276,7 @@
const char * const use_case_table[AUDIO_USECASE_MAX] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
+ [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
[USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
[USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
@@ -615,7 +636,7 @@
struct audio_usecase *usecase)
{
snd_device_t snd_device;
- char mixer_path[50];
+ char mixer_path[MIXER_PATH_MAX_LENGTH];
if (usecase == NULL)
return -EINVAL;
@@ -628,8 +649,13 @@
snd_device = usecase->out_snd_device;
audio_extn_utils_send_app_type_cfg(adev, usecase);
audio_extn_utils_send_audio_calibration(adev, usecase);
- strcpy(mixer_path, use_case_table[usecase->id]);
+
+ // we shouldn't truncate mixer_path
+ ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
+ >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
+ // this also appends to mixer_path
platform_add_backend_name(adev->platform, mixer_path, snd_device);
+
audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
audio_route_apply_and_update_path(adev->audio_route, mixer_path);
@@ -642,7 +668,7 @@
struct audio_usecase *usecase)
{
snd_device_t snd_device;
- char mixer_path[50];
+ char mixer_path[MIXER_PATH_MAX_LENGTH];
if (usecase == NULL)
return -EINVAL;
@@ -652,9 +678,14 @@
snd_device = usecase->in_snd_device;
else
snd_device = usecase->out_snd_device;
- strcpy(mixer_path, use_case_table[usecase->id]);
+
+ // we shouldn't truncate mixer_path
+ ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
+ >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
+ // this also appends to mixer_path
platform_add_backend_name(adev->platform, mixer_path, snd_device);
ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
+
audio_route_reset_and_update_path(adev->audio_route, mixer_path);
audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
@@ -797,6 +828,147 @@
return 0;
}
+#ifdef DYNAMIC_ECNS_ENABLED
+static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
+ struct stream_in *in,
+ struct audio_effect_config effect_config,
+ unsigned int param_value)
+{
+ char mixer_ctl_name[] = "Audio Effect";
+ long set_values[6];
+
+ struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get mixer ctl - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ set_values[0] = 1; //0:Rx 1:Tx
+ set_values[1] = in->app_type_cfg.app_type;
+ set_values[2] = (long)effect_config.module_id;
+ set_values[3] = (long)effect_config.instance_id;
+ set_values[4] = (long)effect_config.param_id;
+ set_values[5] = param_value;
+
+ mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+ return 0;
+
+}
+
+static int update_effect_param_ecns(struct audio_usecase *usecase,
+ unsigned int module_id, int effect_type,
+ unsigned int *param_value)
+{
+ int ret = 0;
+ struct audio_effect_config other_effect_config;
+ struct stream_in *in = NULL;
+
+ if (!usecase)
+ return -EINVAL;
+
+ in = usecase->stream.in;
+
+ /* Get the effect config data of the other effect */
+ ret = platform_get_effect_config_data(usecase->in_snd_device,
+ &other_effect_config,
+ effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
+ if (ret < 0) {
+ ALOGE("%s Failed to get effect params %d", __func__, ret);
+ return ret;
+ }
+
+ if (module_id == other_effect_config.module_id) {
+ //Same module id for AEC/NS. Values need to be combined
+ if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
+ ((effect_type == EFFECT_NS) && (in->enable_aec)))
+ *param_value |= other_effect_config.param_value;
+ }
+
+ return ret;
+}
+
+static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
+ int effect_type, bool enable)
+{
+ struct audio_effect_config effect_config;
+ struct audio_usecase *usecase = NULL;
+ int ret = 0;
+ unsigned int param_value = 0;
+
+ if (!in) {
+ ALOGE("%s: Invalid input stream", __func__);
+ return -EINVAL;
+ }
+
+ ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
+
+ usecase = get_usecase_from_list(adev, in->usecase);
+
+ ret = platform_get_effect_config_data(usecase->in_snd_device,
+ &effect_config, effect_type);
+ if (ret < 0) {
+ ALOGE("%s Failed to get module id %d", __func__, ret);
+ return ret;
+ }
+ ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
+ __func__, effect_config.module_id, in->app_type_cfg.app_type,
+ usecase->id, usecase->in_snd_device);
+
+ if (enable)
+ param_value = effect_config.param_value;
+
+ /*Special handling for AEC & NS effects Param values need to be
+ updated if module ids are same*/
+
+ if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
+ ret = update_effect_param_ecns(usecase, effect_config.module_id,
+ effect_type, ¶m_value);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = send_effect_enable_disable_mixer_ctl(adev, in,
+ effect_config, param_value);
+
+ return ret;
+}
+
+static int check_and_enable_effect(struct audio_device *adev)
+{
+ int ret = 0;
+
+ struct listnode *node;
+ struct stream_in *in = NULL;
+
+ list_for_each(node, &adev->usecase_list)
+ {
+ struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+ in = usecase->stream.in;
+
+ if (in->standby)
+ continue;
+
+ if (in->enable_aec) {
+ ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
+ }
+
+ if (in->enable_ns &&
+ in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+ ret = enable_disable_effect(adev, in, EFFECT_NS, true);
+ }
+ }
+ }
+
+ return ret;
+}
+#else
+#define enable_disable_effect(w, x, y, z) -ENOSYS
+#define check_and_enable_effect(x) -ENOSYS
+#endif
+
/*
legend:
uc - existing usecase
@@ -1022,6 +1194,10 @@
if (usecase->type != PCM_PLAYBACK &&
usecase != uc_info &&
usecase->in_snd_device != snd_device &&
+ ((uc_info->type == VOICE_CALL &&
+ usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
+ platform_check_backends_match(snd_device,\
+ usecase->in_snd_device)) &&
(usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
__func__, use_case_table[usecase->id],
@@ -1134,8 +1310,14 @@
// audio_channel_in_mask_from_count() does the right conversion to either positional or
// indexed mask
for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
- supported_channel_masks[num_masks++] =
+ const audio_channel_mask_t mask =
audio_channel_in_mask_from_count(channel_count);
+ supported_channel_masks[num_masks++] = mask;
+ const audio_channel_mask_t index_mask =
+ audio_channel_mask_for_index_assignment_from_count(channel_count);
+ if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
+ supported_channel_masks[num_masks++] = index_mask;
+ }
}
}
#ifdef NDEBUG
@@ -1270,6 +1452,44 @@
return false;
}
+struct stream_in *adev_get_active_input(const struct audio_device *adev)
+{
+ struct listnode *node;
+ struct stream_in *last_active_in = NULL;
+
+ /* Get last added active input.
+ * TODO: We may use a priority mechanism to pick highest priority active source */
+ list_for_each(node, &adev->usecase_list)
+ {
+ struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+ last_active_in = usecase->stream.in;
+ }
+ }
+
+ return last_active_in;
+}
+
+struct stream_in *get_voice_communication_input(const struct audio_device *adev)
+{
+ struct listnode *node;
+
+ /* First check active inputs with voice communication source and then
+ * any input if audio mode is in communication */
+ list_for_each(node, &adev->usecase_list)
+ {
+ struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
+ usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+ return usecase->stream.in;
+ }
+ }
+ if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+ return adev_get_active_input(adev);
+ }
+ return NULL;
+}
+
int select_devices(struct audio_device *adev,
audio_usecase_t uc_id)
{
@@ -1294,7 +1514,9 @@
(usecase->type == PCM_HFP_CALL)) {
out_snd_device = platform_get_output_snd_device(adev->platform,
usecase->stream.out->devices);
- in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
+ in_snd_device = platform_get_input_snd_device(adev->platform,
+ NULL,
+ usecase->stream.out->devices);
usecase->devices = usecase->stream.out->devices;
} else {
/*
@@ -1309,7 +1531,8 @@
get_voice_usecase_id_from_list(adev));
if ((vc_usecase != NULL) &&
((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
- (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
+ (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
+ (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
in_snd_device = vc_usecase->in_snd_device;
out_snd_device = vc_usecase->out_snd_device;
}
@@ -1326,6 +1549,7 @@
in_snd_device = SND_DEVICE_NONE;
if (out_snd_device == SND_DEVICE_NONE) {
struct stream_out *voip_out = adev->primary_output;
+ struct stream_in *voip_in = get_voice_communication_input(adev);
out_snd_device = platform_get_output_snd_device(adev->platform,
usecase->stream.out->devices);
@@ -1333,11 +1557,8 @@
if (voip_usecase)
voip_out = voip_usecase->stream.out;
- if (usecase->stream.out == voip_out &&
- adev->active_input &&
- (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
- adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
- select_devices(adev, adev->active_input->usecase);
+ if (usecase->stream.out == voip_out && voip_in != NULL) {
+ select_devices(adev, voip_in->usecase);
}
}
} else if (usecase->type == PCM_CAPTURE) {
@@ -1345,9 +1566,9 @@
out_snd_device = SND_DEVICE_NONE;
if (in_snd_device == SND_DEVICE_NONE) {
audio_devices_t out_device = AUDIO_DEVICE_NONE;
- if (adev->active_input &&
- (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
- adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
+ struct stream_in *voip_in = get_voice_communication_input(adev);
+
+ if (voip_in != NULL) {
struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
USECASE_AUDIO_PLAYBACK_VOIP);
@@ -1357,11 +1578,18 @@
out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
} else if (voip_usecase) {
out_device = voip_usecase->stream.out->devices;
- } else if (adev->primary_output) {
+ } else if (adev->primary_output &&
+ !adev->primary_output->standby) {
out_device = adev->primary_output->devices;
+ } else {
+ /* forcing speaker o/p device to get matching i/p pair
+ in case o/p is not routed from same primary HAL */
+ out_device = AUDIO_DEVICE_OUT_SPEAKER;
}
}
- in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
+ in_snd_device = platform_get_input_snd_device(adev->platform,
+ usecase->stream.in,
+ out_device);
}
}
}
@@ -1487,6 +1715,11 @@
audio_extn_ma_set_device(usecase);
+ /* If input stream is already running the effect needs to be
+ applied on the new input device that's being enabled here. */
+ if (in_snd_device != SND_DEVICE_NONE)
+ check_and_enable_effect(adev);
+
/* Applicable only on the targets that has external modem.
* Enable device command should be sent to modem only after
* enabling voice call mixer controls
@@ -1518,17 +1751,6 @@
ALOGV("%s: enter: usecase(%d: %s)", __func__,
in->usecase, use_case_table[in->usecase]);
- if (adev->active_input) {
- if (adev->active_input->usecase == in->usecase) {
- adev->active_input = NULL;
- } else {
- ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
- __func__,
- use_case_table[adev->active_input->usecase],
- use_case_table[in->usecase]);
- }
- }
-
uc_info = get_usecase_from_list(adev, in->usecase);
if (uc_info == NULL) {
ALOGE("%s: Could not find the usecase (%d) in the list",
@@ -1586,7 +1808,6 @@
goto error_config;
}
- adev->active_input = in;
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
uc_info->id = in->usecase;
uc_info->type = PCM_CAPTURE;
@@ -1664,6 +1885,7 @@
}
}
register_in_stream(in);
+ check_and_enable_effect(adev);
audio_streaming_hint_end();
audio_extn_perf_lock_release();
ALOGV("%s: exit", __func__);
@@ -1676,7 +1898,6 @@
audio_extn_perf_lock_release();
error_config:
- adev->active_input = NULL;
ALOGW("%s: exit: status(%d)", __func__, ret);
return ret;
}
@@ -1727,15 +1948,15 @@
struct stream_out *out = (struct stream_out *) context;
struct listnode *item;
- out->offload_state = OFFLOAD_STATE_IDLE;
- out->playback_started = 0;
-
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
set_sched_policy(0, SP_FOREGROUND);
prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
ALOGV("%s", __func__);
+
lock_output_stream(out);
+ out->offload_state = OFFLOAD_STATE_IDLE;
+ out->playback_started = 0;
for (;;) {
struct offload_cmd *cmd = NULL;
stream_callback_event_t event;
@@ -1994,6 +2215,9 @@
audio_low_latency_hint_end();
}
+ if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
+ voice_set_device_mute_flag(adev, false);
+
/* 1. Get and set stream specific mixer controls */
disable_audio_route(adev, uc_info);
@@ -2016,14 +2240,19 @@
}
ret = 0;
}
-
+ /* 1) media + voip output routing to handset must route media back to
+ speaker when voip stops.
+ 2) trigger voip input to reroute when voip output changes to
+ hearing aid. */
if (has_voip_usecase ||
out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
struct listnode *node;
struct audio_usecase *usecase;
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == PCM_CAPTURE || usecase == uc_info)
+ if ((usecase->type == PCM_CAPTURE &&
+ usecase->id != USECASE_AUDIO_RECORD_VOIP)
+ || usecase == uc_info)
continue;
ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
@@ -2038,6 +2267,41 @@
return ret;
}
+struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
+ unsigned int flags, unsigned int pcm_open_retry_count,
+ struct pcm_config *config)
+{
+ struct pcm* pcm = NULL;
+
+ while (1) {
+ pcm = pcm_open(snd_card, pcm_device_id, flags, config);
+ if (pcm == NULL || !pcm_is_ready(pcm)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(pcm));
+ if (pcm != NULL) {
+ pcm_close(pcm);
+ pcm = NULL;
+ }
+ if (pcm_open_retry_count-- == 0)
+ return NULL;
+
+ usleep(PROXY_OPEN_WAIT_TIME * 1000);
+ continue;
+ }
+ break;
+ }
+
+ if (pcm_is_ready(pcm)) {
+ int ret = pcm_prepare(pcm);
+ if (ret < 0) {
+ ALOGE("%s: pcm_prepare returned %d", __func__, ret);
+ pcm_close(pcm);
+ pcm = NULL;
+ }
+ }
+
+ return pcm;
+}
+
int start_output_stream(struct stream_out *out)
{
int ret = 0;
@@ -2045,8 +2309,10 @@
struct audio_device *adev = out->dev;
bool a2dp_combo = false;
- ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
- __func__, out->usecase, use_case_table[out->usecase], out->devices);
+ ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
+ __func__, out->usecase, use_case_table[out->usecase],
+ out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
+ out->devices);
if (out->card_status == CARD_STATUS_OFFLINE ||
adev->card_status == CARD_STATUS_OFFLINE) {
@@ -2117,6 +2383,9 @@
audio_extn_extspk_update(adev->extspk);
+ if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
+ voice_set_device_mute_flag(adev, true);
+
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
__func__, adev->snd_card, out->pcm_device_id, out->config.format);
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -2163,34 +2432,27 @@
flags |= PCM_MMAP | PCM_NOIRQ;
}
- while (1) {
- out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
- flags, &out->config);
- if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
- ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
- if (out->pcm != NULL) {
- pcm_close(out->pcm);
- out->pcm = NULL;
- }
- if (pcm_open_retry_count-- == 0) {
- ret = -EIO;
- goto error_open;
- }
- usleep(PROXY_OPEN_WAIT_TIME * 1000);
- continue;
- }
- break;
+ out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
+ flags, pcm_open_retry_count,
+ &(out->config));
+ if (out->pcm == NULL) {
+ ret = -EIO;
+ goto error_open;
}
- ALOGV("%s: pcm_prepare", __func__);
- if (pcm_is_ready(out->pcm)) {
- ret = pcm_prepare(out->pcm);
- if (ret < 0) {
- ALOGE("%s: pcm_prepare returned %d", __func__, ret);
- pcm_close(out->pcm);
- out->pcm = NULL;
- goto error_open;
+
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
+ if (adev->haptic_pcm != NULL) {
+ pcm_close(adev->haptic_pcm);
+ adev->haptic_pcm = NULL;
}
+ adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
+ adev->haptic_pcm_device_id,
+ flags, pcm_open_retry_count,
+ &(adev->haptics_config));
+ // failure to open haptics pcm shouldnt stop audio,
+ // so do not close audio pcm in case of error
}
+
if (out->realtime) {
ret = pcm_start(out->pcm);
if (ret < 0) {
@@ -2201,6 +2463,7 @@
}
}
}
+
register_out_stream(out);
audio_streaming_hint_end();
audio_extn_perf_lock_release();
@@ -2214,13 +2477,17 @@
// consider a scenario where on pause lower layers are tear down.
// so on resume, swap mixer control need to be sent only when
// backend is active, hence rather than sending from enable device
- // sending it from start of streamtream
+ // sending it from start of stream
platform_set_swap_channels(adev, true);
ALOGV("%s: exit", __func__);
return 0;
error_open:
+ if (adev->haptic_pcm) {
+ pcm_close(adev->haptic_pcm);
+ adev->haptic_pcm = NULL;
+ }
audio_streaming_hint_end();
audio_extn_perf_lock_release();
stop_output_stream(out);
@@ -2394,6 +2661,19 @@
if (out->pcm) {
pcm_close(out->pcm);
out->pcm = NULL;
+
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
+ if (adev->haptic_pcm) {
+ pcm_close(adev->haptic_pcm);
+ adev->haptic_pcm = NULL;
+ }
+
+ if (adev->haptic_buffer != NULL) {
+ free(adev->haptic_buffer);
+ adev->haptic_buffer = NULL;
+ adev->haptic_buffer_size = 0;
+ }
+ }
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
do_stop = out->playback_started;
@@ -2546,10 +2826,13 @@
// otherwise audio is no longer played on the new usb devices.
// By forcing the stream in standby, the usb stack refcount drops to 0
// and the driver is closed.
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
+ if (val == AUDIO_DEVICE_NONE &&
audio_is_usb_out_device(out->devices)) {
- ALOGD("%s() putting the usb device in standby after disconnection", __func__);
- out_standby_l(&out->stream.common);
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ ALOGD("%s() putting the usb device in standby after disconnection", __func__);
+ out_standby_l(&out->stream.common);
+ }
+ val = AUDIO_DEVICE_OUT_SPEAKER;
}
pthread_mutex_lock(&adev->lock);
@@ -2712,7 +2995,7 @@
struct str_parms *reply,
audio_channel_mask_t *supported_channel_masks) {
int ret = -1;
- char value[256];
+ char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
bool first = true;
size_t i, j;
@@ -3091,11 +3374,77 @@
request_out_focus(out, ns);
bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
- if (use_mmap)
+ if (use_mmap) {
ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
- else
- ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
+ } else {
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
+ size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
+ size_t bytes_per_sample = audio_bytes_per_sample(out->format);
+ size_t frame_size = channel_count * bytes_per_sample;
+ size_t frame_count = bytes_to_write / frame_size;
+ bool force_haptic_path =
+ property_get_bool("vendor.audio.test_haptic", false);
+
+ // extract Haptics data from Audio buffer
+ bool alloc_haptic_buffer = false;
+ int haptic_channel_count = adev->haptics_config.channels;
+ size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
+ size_t audio_frame_size = frame_size - haptic_frame_size;
+ size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
+
+ if (adev->haptic_buffer == NULL) {
+ alloc_haptic_buffer = true;
+ } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
+ free(adev->haptic_buffer);
+ adev->haptic_buffer_size = 0;
+ alloc_haptic_buffer = true;
+ }
+
+ if (alloc_haptic_buffer) {
+ adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
+ adev->haptic_buffer_size = total_haptic_buffer_size;
+ }
+
+ size_t src_index = 0, aud_index = 0, hap_index = 0;
+ uint8_t *audio_buffer = (uint8_t *)buffer;
+ uint8_t *haptic_buffer = adev->haptic_buffer;
+
+ // This is required for testing only. This works for stereo data only.
+ // One channel is fed to audio stream and other to haptic stream for testing.
+ if (force_haptic_path) {
+ audio_frame_size = haptic_frame_size = bytes_per_sample;
+ }
+
+ for (size_t i = 0; i < frame_count; i++) {
+ for (size_t j = 0; j < audio_frame_size; j++)
+ audio_buffer[aud_index++] = audio_buffer[src_index++];
+
+ for (size_t j = 0; j < haptic_frame_size; j++)
+ haptic_buffer[hap_index++] = audio_buffer[src_index++];
+ }
+
+ // This is required for testing only.
+ // Discard haptic channel data.
+ if (force_haptic_path) {
+ src_index += haptic_frame_size;
+ }
+
+ // write to audio pipeline
+ ret = pcm_write(out->pcm,
+ (void *)audio_buffer,
+ frame_count * audio_frame_size);
+
+ // write to haptics pipeline
+ if (adev->haptic_pcm)
+ ret = pcm_write(adev->haptic_pcm,
+ (void *)adev->haptic_buffer,
+ frame_count * haptic_frame_size);
+
+ } else {
+ ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
+ }
+ }
release_out_focus(out, ns);
} else {
LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
@@ -3902,6 +4251,8 @@
effect_descriptor_t desc;
status = (*effect)->get_descriptor(effect, &desc);
+ ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
+
if (status != 0)
return status;
@@ -3926,14 +4277,18 @@
select_devices(adev, usecase->id);
}
}
- if (!in->standby)
+ if (!in->standby
+ && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
select_devices(in->dev, in->usecase);
}
if (in->enable_ns != enable &&
(memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
in->enable_ns = enable;
- if (!in->standby)
- select_devices(in->dev, in->usecase);
+ if (!in->standby) {
+ if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
+ || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
+ select_devices(in->dev, in->usecase);
+ }
}
pthread_mutex_unlock(&in->dev->lock);
pthread_mutex_unlock(&in->lock);
@@ -4153,6 +4508,67 @@
return ret;
}
+static int in_set_microphone_direction(const struct audio_stream_in *stream,
+ audio_microphone_direction_t dir) {
+ (void)stream;
+ (void)dir;
+ ALOGVV("%s", __func__);
+ return -ENOSYS;
+}
+
+static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
+ (void)stream;
+ (void)zoom;
+ ALOGVV("%s", __func__);
+ return -ENOSYS;
+}
+
+static void in_update_sink_metadata(struct audio_stream_in *stream,
+ const struct sink_metadata *sink_metadata) {
+
+ if (stream == NULL
+ || sink_metadata == NULL
+ || sink_metadata->tracks == NULL) {
+ return;
+ }
+
+ int error = 0;
+ struct stream_in *in = (struct stream_in *)stream;
+ struct audio_device *adev = in->dev;
+ audio_devices_t device = AUDIO_DEVICE_NONE;
+
+ if (sink_metadata->track_count != 0)
+ device = sink_metadata->tracks->dest_device;
+
+ lock_input_stream(in);
+ pthread_mutex_lock(&adev->lock);
+ ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
+
+ if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
+ && device != AUDIO_DEVICE_NONE
+ && adev->voice_tx_output != NULL) {
+ /* Use the rx device from afe-proxy record to route voice call because
+ there is no routing if tx device is on primary hal and rx device
+ is on other hal during voice call. */
+ adev->voice_tx_output->devices = device;
+
+ if (!voice_is_call_state_active(adev)) {
+ if (adev->mode == AUDIO_MODE_IN_CALL) {
+ adev->current_call_output = adev->voice_tx_output;
+ error = voice_start_call(adev);
+ if (error != 0)
+ ALOGE("%s: start voice call failed %d", __func__, error);
+ }
+ } else {
+ adev->current_call_output = adev->voice_tx_output;
+ voice_update_devices_for_all_voice_usecases(adev);
+ }
+ }
+
+ pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&in->lock);
+}
+
static int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
@@ -4167,6 +4583,8 @@
bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
bool is_usb_dev = audio_is_usb_out_device(devices) &&
(devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
+ bool force_haptic_path =
+ property_get_bool("vendor.audio.test_haptic", false);
if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
return -ENOSYS;
@@ -4174,6 +4592,7 @@
ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
__func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
+
*stream_out = NULL;
out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
@@ -4504,8 +4923,24 @@
out->stream.create_mmap_buffer = out_create_mmap_buffer;
out->stream.get_mmap_position = out_get_mmap_position;
} else {
- out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
- out->config = pcm_config_low_latency;
+ if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
+ out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
+ adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
+ if (adev->haptic_pcm_device_id < 0) {
+ ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
+ __func__, adev->haptic_pcm_device_id, out->usecase);
+ ret = -ENOSYS;
+ goto error_open;
+ }
+ out->config = pcm_config_haptics_audio;
+ if (force_haptic_path)
+ adev->haptics_config = pcm_config_haptics_audio;
+ else
+ adev->haptics_config = pcm_config_haptics;
+ } else {
+ out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
+ out->config = pcm_config_low_latency;
+ }
}
if (config->sample_rate == 0) {
@@ -4513,11 +4948,13 @@
} else {
out->sample_rate = config->sample_rate;
}
+
if (config->channel_mask == AUDIO_CHANNEL_NONE) {
out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
} else {
out->channel_mask = config->channel_mask;
}
+
if (config->format == AUDIO_FORMAT_DEFAULT)
out->format = audio_format_from_pcm_format(out->config.format);
else if (!audio_is_linear_pcm(config->format)) {
@@ -4529,8 +4966,25 @@
}
out->config.rate = out->sample_rate;
- out->config.channels =
- audio_channel_count_from_out_mask(out->channel_mask);
+
+ if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
+ out->config.channels =
+ audio_channel_count_from_out_mask(out->channel_mask &
+ ~AUDIO_CHANNEL_HAPTIC_ALL);
+
+ if (force_haptic_path) {
+ out->config.channels = 1;
+ adev->haptics_config.channels = 1;
+ } else {
+ adev->haptics_config.channels =
+ audio_channel_count_from_out_mask(out->channel_mask &
+ AUDIO_CHANNEL_HAPTIC_ALL);
+ }
+ } else {
+ out->config.channels =
+ audio_channel_count_from_out_mask(out->channel_mask);
+ }
+
if (out->format != audio_format_from_pcm_format(out->config.format)) {
out->config.format = pcm_format_from_audio_format(out->format);
}
@@ -5030,7 +5484,10 @@
devices,
flags,
source);
- ALOGV("%s: enter", __func__);
+ ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
+ " sample_rate %u, channel_mask %#x, format %#x",
+ __func__, flags, is_usb_dev, may_use_hifi_record,
+ config->sample_rate, config->channel_mask, config->format);
*stream_in = NULL;
if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
@@ -5077,6 +5534,9 @@
in->stream.get_input_frames_lost = in_get_input_frames_lost;
in->stream.get_capture_position = in_get_capture_position;
in->stream.get_active_microphones = in_get_active_microphones;
+ in->stream.set_microphone_direction = in_set_microphone_direction;
+ in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
+ in->stream.update_sink_metadata = in_update_sink_metadata;
in->device = devices;
in->source = source;
@@ -5085,7 +5545,7 @@
in->capture_handle = handle;
in->flags = flags;
- ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
+ ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
if (source == AUDIO_SOURCE_VOICE_UPLINK ||
source == AUDIO_SOURCE_VOICE_DOWNLINK) {
/* Force channel config requested to mono if incall
@@ -5401,13 +5861,10 @@
uc_info.id = audio_usecase;
uc_info.type = usecase_type;
if (dir) {
- adev->active_input = ∈
memset(&in, 0, sizeof(in));
in.device = audio_device;
in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
uc_info.stream.in = ∈
- } else {
- adev->active_input = NULL;
}
memset(&out, 0, sizeof(out));
out.devices = audio_device; /* only field needed in select_devices */
@@ -5441,7 +5898,6 @@
list_remove(&uc_info.list);
}
}
- adev->active_input = NULL; /* restore adev state */
return 0;
}
@@ -5646,7 +6102,6 @@
/* Set the default route before the PCM stream is opened */
pthread_mutex_lock(&adev->lock);
adev->mode = AUDIO_MODE_NORMAL;
- adev->active_input = NULL;
adev->primary_output = NULL;
adev->bluetooth_nrec = true;
adev->acdb_settings = TTY_MODE_OFF;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 0b3b028..f28505d 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -82,6 +82,7 @@
USECASE_AUDIO_PLAYBACK_TTS,
USECASE_AUDIO_PLAYBACK_ULL,
USECASE_AUDIO_PLAYBACK_MMAP,
+ USECASE_AUDIO_PLAYBACK_WITH_HAPTICS,
/* HFP Use case*/
USECASE_AUDIO_HFP_SCO,
@@ -340,7 +341,6 @@
pthread_mutex_t lock; /* see note below on mutex acquisition order */
struct mixer *mixer;
audio_mode_t mode;
- struct stream_in *active_input;
struct stream_out *primary_output;
struct stream_out *voice_tx_output;
struct stream_out *current_call_output;
@@ -357,6 +357,7 @@
bool enable_voicerx;
bool enable_hfp;
bool mic_break_enabled;
+ bool use_voice_device_mute;
int snd_card;
void *platform;
@@ -381,6 +382,13 @@
void *adm_data;
void *adm_lib;
+
+ struct pcm_config haptics_config;
+ struct pcm *haptic_pcm;
+ int haptic_pcm_device_id;
+ uint8_t *haptic_buffer;
+ size_t haptic_buffer_size;
+
adm_init_t adm_init;
adm_deinit_t adm_deinit;
adm_register_input_stream_t adm_register_input_stream;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 750d4e5..3602b97 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -81,6 +81,8 @@
#define TOSTRING_(x) #x
#define TOSTRING(x) TOSTRING_(x)
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
[WCD9XXX_MBHC_CAL] = "mbhc_cal",
};
@@ -301,6 +303,34 @@
[SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
};
+static struct audio_effect_config \
+ effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_COUNT] = {
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_AEC] = \
+ {TX_VOICE_DM_FV5_BROADSIDE, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)][EFFECT_NS] = \
+ {TX_VOICE_DM_FV5_BROADSIDE, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+};
+
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
static int acdb_device_table[SND_DEVICE_MAX] = {
[SND_DEVICE_NONE] = -1,
@@ -1132,7 +1162,8 @@
/* Initialize ACDB and PCM ID's */
strlcpy(platform_info_path, PLATFORM_INFO_XML_PATH, MAX_MIXER_XML_PATH);
resolve_config_file(platform_info_path);
- platform_info_init(platform_info_path, my_data);
+ platform_info_init(platform_info_path, my_data,
+ true, &platform_set_parameters);
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
@@ -1370,6 +1401,11 @@
return device_id;
}
+int platform_get_haptics_pcm_device_id()
+{
+ return -1;
+}
+
static int find_index(struct name_to_index * table, int32_t len, const char * name)
{
int ret = 0;
@@ -1415,6 +1451,42 @@
return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
}
+int platform_get_effect_config_data(snd_device_t snd_device,
+ struct audio_effect_config *effect_config,
+ effect_type_t effect_type)
+{
+ int ret = 0;
+
+ if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+ (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+ ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+ __func__, snd_device, effect_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (effect_config == NULL) {
+ ALOGE("%s: Invalid effect_config", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGV("%s: snd_device = %d module_id = %d",
+ __func__, snd_device,
+ effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+ *effect_config = effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type];
+
+done:
+ return ret;
+}
+
+void platform_add_external_specific_device(snd_device_t snd_device __unused,
+ const char *name __unused,
+ unsigned int acdb_id __unused)
+{
+ return;
+}
+
void platform_add_operator_specific_device(snd_device_t snd_device,
const char *operator,
const char *mixer_path,
@@ -1498,6 +1570,27 @@
}
}
return key;
+
+int platform_set_effect_config_data(snd_device_t snd_device,
+ struct audio_effect_config effect_config,
+ effect_type_t effect_type)
+{
+ int ret = 0;
+
+ if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+ (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+ ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+ __func__, snd_device, effect_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+ effect_config.instance_id, effect_config.param_id,
+ effect_config.param_value);
+ effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+done:
+ return ret;
}
int platform_get_default_app_type_v2(void *platform, usecase_type_t type, int *app_type)
@@ -1651,6 +1744,7 @@
struct audio_device *adev = my_data->adev;
struct mixer_ctl *ctl;
const char *mixer_ctl_name = "Voice Rx Gain";
+ const char *mute_mixer_ctl_name = "Voice Rx Device Mute";
int vol_index = 0, ret = 0;
uint32_t set_values[ ] = {0,
ALL_SESSION_VSID,
@@ -1661,7 +1755,6 @@
// But this values don't changed in kernel. So, below change is need.
vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, my_data->max_vol_index);
set_values[0] = vol_index;
-
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
@@ -1671,6 +1764,23 @@
ALOGV("Setting voice volume index: %d", set_values[0]);
ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+ // Send mute command in case volume index is max since indexes are inverted
+ // for mixer controls.
+ if (vol_index == my_data->max_vol_index) {
+ set_values[0] = 1;
+ }
+ else {
+ set_values[0] = 0;
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mute_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mute_mixer_ctl_name);
+ return -EINVAL;
+ }
+ ALOGV("%s: Setting RX Device Mute to: %d", __func__, set_values[0]);
+ mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
return ret;
}
@@ -1780,10 +1890,6 @@
audio_mode_t mode = adev->mode;
snd_device_t snd_device = SND_DEVICE_NONE;
- audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
- AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
- int channel_count = popcount(channel_mask);
-
ALOGV("%s: enter: output devices(%#x)", __func__, devices);
if (devices == AUDIO_DEVICE_NONE ||
devices & AUDIO_DEVICE_BIT_IN) {
@@ -1916,21 +2022,157 @@
return snd_device;
}
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+ struct stream_in *in __unused,
+ audio_devices_t out_device,
+ audio_devices_t in_device)
+{
+ struct audio_device *adev = my_data->adev;
+ snd_device_t snd_device = SND_DEVICE_NONE;
+
+ if (my_data->fluence_type != FLUENCE_NONE) {
+ switch(AUDIO_DEVICE_BIT_IN | in_device) {
+ case AUDIO_DEVICE_IN_BACK_MIC:
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ }
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+ break;
+ case AUDIO_DEVICE_IN_BUILTIN_MIC:
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+ break;
+ default:
+ ALOGE("%s: Unsupported in_device %#x", __func__, in_device);
+ break;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ }
+
+ return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+ struct stream_in *in,
+ audio_devices_t out_device,
+ audio_devices_t in_device)
+{
+ struct audio_device *adev = my_data->adev;
+ snd_device_t snd_device = SND_DEVICE_NONE;
+
+ if (my_data->fluence_type != FLUENCE_NONE &&
+ in->enable_aec &&
+ in->enable_ns) {
+ if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ }
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+ } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+ } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ } else if (my_data->fluence_type != FLUENCE_NONE &&
+ in->enable_aec) {
+ if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+ }
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+ } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+ } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ } else if (my_data->fluence_type != FLUENCE_NONE &&
+ in->enable_ns) {
+ if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+ }
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+ } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+ } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
+ }
+ platform_set_echo_reference(adev, false, out_device);
+ } else
+ platform_set_echo_reference(adev, false, out_device);
+
+ return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
+snd_device_t platform_get_input_snd_device(void *platform,
+ struct stream_in *in,
+ audio_devices_t out_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
- audio_source_t source = (adev->active_input == NULL) ?
- AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
- audio_mode_t mode = adev->mode;
- audio_devices_t in_device = ((adev->active_input == NULL) ?
- AUDIO_DEVICE_NONE : adev->active_input->device)
- & ~AUDIO_DEVICE_BIT_IN;
- audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
- AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+ audio_mode_t mode = adev->mode;
snd_device_t snd_device = SND_DEVICE_NONE;
- int channel_count = popcount(channel_mask);
+
+ if (in == NULL) {
+ in = adev_get_active_input(adev);
+ }
+
+ audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+ audio_devices_t in_device =
+ ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+ audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+ int channel_count = audio_channel_count_from_in_mask(channel_mask);
ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
__func__, out_device, in_device);
@@ -2025,7 +2267,7 @@
if (channel_count == 2) {
snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
adev->acdb_settings |= DMIC_FLAG;
- } else if (adev->active_input->enable_ns)
+ } else if (in->enable_ns)
snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
else if (my_data->fluence_type != FLUENCE_NONE &&
my_data->fluence_in_voice_rec) {
@@ -2039,85 +2281,10 @@
(mode == AUDIO_MODE_IN_COMMUNICATION)) {
if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
in_device = AUDIO_DEVICE_IN_BACK_MIC;
- if (adev->active_input) {
- if (my_data->fluence_type != FLUENCE_NONE &&
- adev->active_input->enable_aec &&
- adev->active_input->enable_ns) {
- if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_in_spkr_mode) {
- if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
- } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- if (my_data->fluence_mode == FLUENCE_BROADSIDE)
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
- else
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
- }
- adev->acdb_settings |= DMIC_FLAG;
- } else
- snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
- } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
- adev->acdb_settings |= DMIC_FLAG;
- } else
- snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
- } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
- snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
- }
- platform_set_echo_reference(adev, true, out_device);
- } else if (my_data->fluence_type != FLUENCE_NONE &&
- adev->active_input->enable_aec) {
- if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_in_spkr_mode) {
- if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
- } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- if (my_data->fluence_mode == FLUENCE_BROADSIDE)
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
- else
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
- }
- adev->acdb_settings |= DMIC_FLAG;
- } else
- snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
- } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
- adev->acdb_settings |= DMIC_FLAG;
- } else
- snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
- } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
- snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
- }
- platform_set_echo_reference(adev, true, out_device);
- } else if (my_data->fluence_type != FLUENCE_NONE &&
- adev->active_input->enable_ns) {
- if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_in_spkr_mode) {
- if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
- } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- if (my_data->fluence_mode == FLUENCE_BROADSIDE)
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
- else
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
- }
- adev->acdb_settings |= DMIC_FLAG;
- } else
- snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
- } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
- adev->acdb_settings |= DMIC_FLAG;
- } else
- snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
- } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
- snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
- }
- platform_set_echo_reference(adev, false, out_device);
- } else
- platform_set_echo_reference(adev, false, out_device);
+
+ if (in) {
+ snd_device = get_snd_device_for_voice_comm(my_data, in,
+ out_device, in_device);
}
} else if (source == AUDIO_SOURCE_FM_TUNER) {
snd_device = SND_DEVICE_IN_CAPTURE_FM;
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 9913322..f3dbc3d 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -250,6 +250,11 @@
#define AUDIO_MAKE_STRING_FROM_ENUM(X) { #X, X }
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
#define LIB_CSD_CLIENT "libcsd-client.so"
/* CSD-CLIENT related functions */
typedef int (*init_t)();
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index bd8c41c..ae65ef2 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -424,6 +424,11 @@
return device_id;
}
+int platform_get_haptics_pcm_device_id()
+{
+ return -1;
+}
+
int platform_get_snd_device_index(char *snd_device_index_name __unused)
{
return -ENODEV;
@@ -448,6 +453,13 @@
return -ENOSYS;
}
+void platform_add_external_specific_device(snd_device_t snd_device __unused,
+ const char *name __unused,
+ unsigned int acdb_id __unused)
+{
+ return;
+}
+
void platform_add_operator_specific_device(snd_device_t snd_device __unused,
const char *operator __unused,
const char *mixer_path __unused,
@@ -729,21 +741,24 @@
return snd_device;
}
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+snd_device_t platform_get_input_snd_device(void *platform,
+ struct stream_in *in,
+ audio_devices_t out_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
- audio_source_t source = (adev->active_input == NULL) ?
- AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
- audio_mode_t mode = adev->mode;
- audio_devices_t in_device = ((adev->active_input == NULL) ?
- AUDIO_DEVICE_NONE : adev->active_input->device)
- & ~AUDIO_DEVICE_BIT_IN;
- audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
- AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+ audio_mode_t mode = adev->mode;
snd_device_t snd_device = SND_DEVICE_NONE;
+ if (in == NULL) {
+ in = adev_get_active_input(adev);
+ }
+
+ audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+ audio_devices_t in_device =
+ ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+ audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+
ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
__func__, out_device, in_device);
if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
@@ -827,8 +842,8 @@
mode == AUDIO_MODE_IN_COMMUNICATION) {
if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
in_device = AUDIO_DEVICE_IN_BACK_MIC;
- if (adev->active_input) {
- if (adev->active_input->enable_aec) {
+ if (in) {
+ if (in != NULL && in->enable_aec) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 5a36f0c..eb4bb4a 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -72,6 +72,8 @@
#define TOSTRING_(x) #x
#define TOSTRING(x) TOSTRING_(x)
+#define GET_IN_DEVICE_INDEX(SND_DEVICE) ((SND_DEVICE) - (SND_DEVICE_IN_BEGIN))
+
struct audio_block_header
{
int reserved;
@@ -99,6 +101,12 @@
int acdb_id;
};
+struct external_specific_device {
+ struct listnode list;
+ char *usbid;
+ int acdb_id;
+};
+
#define BE_DAI_NAME_MAX_LENGTH 24
struct be_dai_name_struct {
unsigned int be_id;
@@ -112,6 +120,7 @@
static struct listnode operator_info_list;
static struct listnode *operator_specific_device_table[SND_DEVICE_MAX];
+static struct listnode *external_specific_device_table[SND_DEVICE_MAX];
#define AUDIO_PARAMETER_KEY_AUD_CALDATA "cal_data"
@@ -125,6 +134,10 @@
uint32_t sampling_rate;
uint32_t cal_type;
uint32_t module_id;
+#ifdef PLATFORM_SM8150
+ uint16_t instance_id;
+ uint16_t reserved;
+#endif
uint32_t param_id;
} acdb_audio_cal_cfg_t;
@@ -178,6 +191,8 @@
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
DEEP_BUFFER_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = {AUDIO_HAPTICS_PCM_DEVICE,
+ AUDIO_HAPTICS_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE,
@@ -287,6 +302,7 @@
[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco",
[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb",
[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb",
+ [SND_DEVICE_OUT_VOICE_HEARING_AID] = "hearing-aid",
/* Capture sound devices */
[SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -364,6 +380,33 @@
[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = "camcorder-mic",
[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = "camcorder-mic",
[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic",
+ [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic",
+ [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
+ [SND_DEVICE_IN_VOICE_HEARING_AID] = "hearing-aid-mic",
+};
+
+static struct audio_effect_config \
+ effect_config_table[GET_IN_DEVICE_INDEX(SND_DEVICE_MAX)][EFFECT_COUNT] = {
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FLUENCE_PROV2, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_DM, 0x0, 0x10EAF, 0x02},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_AEC] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x01},
+ [GET_IN_DEVICE_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)][EFFECT_NS] = \
+ {TX_VOICE_FV5ECNS_SM, 0x0, 0x10EAF, 0x02},
};
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -412,6 +455,7 @@
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
[SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = ACDB_ID_VOICE_SPEAKER,
+ [SND_DEVICE_OUT_VOICE_HEARING_AID] = 45,
[SND_DEVICE_IN_HANDSET_MIC] = 4,
[SND_DEVICE_IN_HANDSET_MIC_AEC] = 106,
@@ -487,6 +531,9 @@
[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = 61,
[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = 61,
[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61,
+ [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129,
+ [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129,
+ [SND_DEVICE_IN_VOICE_HEARING_AID] = 44,
};
// Platform specific backend bit width table
@@ -545,6 +592,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
{TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET_SPEC)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEARING_AID)},
/* in */
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
@@ -621,8 +669,12 @@
{TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE)},
{TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE)},
{TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEARING_AID)},
+
/* For legacy xml file parsing */
{TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)},
};
static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -631,6 +683,7 @@
static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_HIFI)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)},
@@ -690,6 +743,27 @@
static int init_be_dai_name_table(struct audio_device *adev);
+static bool is_usb_snd_dev(snd_device_t snd_device)
+{
+ if (snd_device < SND_DEVICE_IN_BEGIN) {
+ if (snd_device == SND_DEVICE_OUT_USB_HEADSET ||\
+ snd_device == SND_DEVICE_OUT_USB_HEADPHONES ||\
+ snd_device == SND_DEVICE_OUT_VOICE_USB_HEADPHONES ||\
+ snd_device == SND_DEVICE_OUT_VOICE_USB_HEADSET ||\
+ snd_device == SND_DEVICE_OUT_VOICE_TTY_FULL_USB ||\
+ snd_device == SND_DEVICE_OUT_VOICE_TTY_VCO_USB)
+ return true;
+ } else {
+ if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC ||\
+ snd_device == SND_DEVICE_IN_USB_HEADSET_MIC_AEC ||\
+ snd_device == SND_DEVICE_IN_VOICE_USB_HEADSET_MIC ||\
+ snd_device == SND_DEVICE_IN_UNPROCESSED_USB_HEADSET_MIC ||\
+ snd_device == SND_DEVICE_IN_VOICE_RECOG_USB_HEADSET_MIC)
+ return true;
+ }
+ return false;
+}
+
static void check_operator()
{
char value[PROPERTY_VALUE_MAX];
@@ -779,6 +853,30 @@
return ret;
}
+static int get_external_specific_device_acdb_id(snd_device_t snd_device)
+{
+ struct external_specific_device *ext_dev;
+ int ret = acdb_device_table[snd_device];
+ char *usbid = NULL;
+ struct listnode *node;
+
+ if (is_usb_snd_dev(snd_device))
+ usbid = audio_extn_usb_usbid();
+
+ if (usbid) {
+ list_for_each(node, external_specific_device_table[snd_device]) {
+ ext_dev = node_to_item(node, struct external_specific_device, list);
+ if (ext_dev->usbid && !strcmp(usbid, ext_dev->usbid)) {
+ ret = ext_dev->acdb_id;
+ break;
+ }
+ }
+
+ free(usbid);
+ }
+ return ret;
+}
+
static const char *get_operator_specific_device_mixer_path(snd_device_t snd_device)
{
struct operator_specific_device *device;
@@ -911,7 +1009,9 @@
if (cal.dev_id) {
if (audio_is_input_device(cal.dev_id)) {
- cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
+ // FIXME: why pass an input device whereas
+ // platform_get_input_snd_device() expects as an output device?
+ cal.snd_dev_id = platform_get_input_snd_device(platform, NULL, cal.dev_id);
} else {
cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
}
@@ -1208,6 +1308,7 @@
backend_tag_table[dev] = NULL;
hw_interface_table[dev] = NULL;
operator_specific_device_table[dev] = NULL;
+ external_specific_device_table[dev] = NULL;
}
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
@@ -1247,6 +1348,7 @@
backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp");
backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = strdup("speaker-safe-and-bt-a2dp");
backend_tag_table[SND_DEVICE_OUT_USB_HEADSET_SPEC] = strdup("usb-headset");
+ backend_tag_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("hearing-aid");
hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX");
@@ -1295,6 +1397,11 @@
hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"),
hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"),
+ /* So far, primary hal doesn't support hearing aid device.
+ Need snd_device to route voice call and use specific acdb tuning.
+ Also, BT_RX is a virtual port to indicate bluetooth hearing aid. */
+ hw_interface_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("BT_RX"),
+
hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] = strdup("USB_AUDIO_TX");
@@ -1336,6 +1443,8 @@
hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_STEREO] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_VOICE_DMIC] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_VOICE_DMIC_TMUS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP] = strdup("SLIMBUS_0_TX");
@@ -1360,6 +1469,8 @@
hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX");
hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_HEARING_AID] = strdup("SLIMBUS_0_TX");
+
my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
}
@@ -1649,7 +1760,8 @@
my_data->declared_mic_count = 0;
/* Initialize platform specific ids and/or backends*/
- platform_info_init(platform_info_file, my_data);
+ platform_info_init(platform_info_file, my_data,
+ true, &platform_set_parameters);
ALOGD("%s: Loading mixer file: %s", __func__, mixer_xml_file);
adev->audio_route = audio_route_init(snd_card_num, mixer_xml_file);
@@ -1864,6 +1976,7 @@
int32_t dev;
struct operator_info *info_item;
struct operator_specific_device *device_item;
+ struct external_specific_device *ext_dev;
struct app_type_entry *ap;
struct listnode *node;
@@ -1890,6 +2003,17 @@
}
free(operator_specific_device_table[dev]);
}
+
+ if (external_specific_device_table[dev]) {
+ while (!list_empty(external_specific_device_table[dev])) {
+ node = list_head(external_specific_device_table[dev]);
+ list_remove(node);
+ ext_dev = node_to_item(node, struct external_specific_device, list);
+ free(ext_dev->usbid);
+ free(ext_dev);
+ }
+ free(external_specific_device_table[dev]);
+ }
}
if (my_data->snd_card_name)
@@ -2019,6 +2143,11 @@
return device_id;
}
+int platform_get_haptics_pcm_device_id()
+{
+ return HAPTICS_PCM_DEVICE;
+}
+
static int find_index(const struct name_to_index * table, int32_t len,
const char * name)
{
@@ -2060,6 +2189,57 @@
return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
}
+int platform_get_effect_config_data(snd_device_t snd_device,
+ struct audio_effect_config *effect_config,
+ effect_type_t effect_type)
+{
+ int ret = 0;
+
+ if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+ (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+ ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+ __func__, snd_device, effect_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (effect_config == NULL) {
+ ALOGE("%s: Invalid effect_config", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGV("%s: snd_device = %d module_id = %d",
+ __func__, snd_device, effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type].module_id);
+ *effect_config = effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type];
+
+done:
+ return ret;
+}
+
+int platform_set_effect_config_data(snd_device_t snd_device,
+ struct audio_effect_config effect_config,
+ effect_type_t effect_type)
+{
+ int ret = 0;
+
+ if ((snd_device < SND_DEVICE_IN_BEGIN) || (snd_device >= SND_DEVICE_MAX) ||
+ (effect_type <= EFFECT_NONE) || (effect_type >= EFFECT_COUNT)) {
+ ALOGE("%s: Invalid snd_device = %d or effect_type = %d",
+ __func__, snd_device, effect_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGV("%s 0x%x 0x%x 0x%x 0x%x", __func__, effect_config.module_id,
+ effect_config.instance_id, effect_config.param_id,
+ effect_config.param_value);
+ effect_config_table[GET_IN_DEVICE_INDEX(snd_device)][effect_type] = effect_config;
+
+done:
+ return ret;
+}
+
void platform_add_operator_specific_device(snd_device_t snd_device,
const char *operator,
const char *mixer_path,
@@ -2086,6 +2266,30 @@
}
+void platform_add_external_specific_device(snd_device_t snd_device,
+ const char *usbid,
+ unsigned int acdb_id)
+{
+ struct external_specific_device *device;
+
+ if (external_specific_device_table[snd_device] == NULL) {
+ external_specific_device_table[snd_device] =
+ (struct listnode *)calloc(1, sizeof(struct listnode));
+ list_init(external_specific_device_table[snd_device]);
+ }
+
+ device = (struct external_specific_device *)calloc(1, sizeof(struct external_specific_device));
+
+ device->usbid = strdup(usbid);
+ device->acdb_id = acdb_id;
+
+ list_add_tail(external_specific_device_table[snd_device], &device->list);
+
+ ALOGD("%s: device[%s] usbid[%s] -> acdb_id[%d]", __func__,
+ platform_get_snd_device_name(snd_device), usbid, acdb_id);
+}
+
+
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
{
int ret = 0;
@@ -2119,6 +2323,8 @@
if (operator_specific_device_table[snd_device] != NULL)
return get_operator_specific_device_acdb_id(snd_device);
+ else if (external_specific_device_table[snd_device] != NULL)
+ return get_external_specific_device_acdb_id(snd_device);
else
return acdb_device_table[snd_device];
}
@@ -2512,7 +2718,7 @@
__func__, mixer_ctl_name);
return -EINVAL;
}
- ALOGV("Setting voice mute state: %d", state);
+ ALOGV("%s: Setting voice mute state: %d", __func__, state);
mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
if (my_data->csd != NULL) {
@@ -2801,8 +3007,11 @@
snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
else
snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
- } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX)
+ } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX) {
snd_device = SND_DEVICE_OUT_VOICE_TX;
+ } else if (devices & AUDIO_DEVICE_OUT_HEARING_AID) {
+ snd_device = SND_DEVICE_OUT_VOICE_HEARING_AID;
+ }
if (snd_device != SND_DEVICE_NONE) {
goto exit;
@@ -2858,24 +3067,148 @@
return snd_device;
}
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+#ifdef DYNAMIC_ECNS_ENABLED
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+ struct stream_in *in __unused,
+ audio_devices_t out_device,
+ audio_devices_t in_device)
+{
+ struct audio_device *adev = my_data->adev;
+ snd_device_t snd_device = SND_DEVICE_NONE;
+
+ if (my_data->fluence_type != FLUENCE_DISABLE) {
+ switch(AUDIO_DEVICE_BIT_IN | in_device) {
+ case AUDIO_DEVICE_IN_BACK_MIC:
+ if (my_data->fluence_in_spkr_mode) {
+ if ((my_data->fluence_type & FLUENCE_PRO_ENABLE) &&
+ (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+ } else if (((my_data->fluence_type & FLUENCE_PRO_ENABLE) ||
+ (my_data->fluence_type & FLUENCE_ENABLE)) &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ }
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+ break;
+ case AUDIO_DEVICE_IN_BUILTIN_MIC:
+ if (((my_data->fluence_type & FLUENCE_PRO_ENABLE) ||
+ (my_data->fluence_type & FLUENCE_ENABLE)) &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+ adev->acdb_settings |= DMIC_FLAG;
+ } else
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+ break;
+ default:
+ ALOGE("%s: Unsupported in_device %#x", __func__, in_device);
+ break;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ }
+
+ return snd_device;
+}
+#else
+static snd_device_t get_snd_device_for_voice_comm(struct platform_data *my_data,
+ struct stream_in *in,
+ audio_devices_t out_device,
+ audio_devices_t in_device)
+{
+ struct audio_device *adev = my_data->adev;
+ snd_device_t snd_device = SND_DEVICE_NONE;
+
+ if (in->enable_aec &&
+ in->enable_ns) {
+ if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (my_data->fluence_in_spkr_mode &&
+ my_data->fluence_in_voice_comm &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ } else {
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+ }
+ } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ if (my_data->fluence_in_voice_comm &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
+ } else {
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+ }
+ } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
+ } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
+ snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ } else if (in->enable_aec) {
+ if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (my_data->fluence_in_spkr_mode &&
+ my_data->fluence_in_voice_comm &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+ } else {
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+ }
+ } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ if (my_data->fluence_in_voice_comm &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
+ } else {
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+ }
+ } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
+ } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
+ snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ } else if (in->enable_ns) {
+ if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (my_data->fluence_in_spkr_mode &&
+ my_data->fluence_in_voice_comm &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+ } else {
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+ }
+ } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ if (my_data->fluence_in_voice_comm &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
+ } else {
+ snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+ }
+ }
+ }
+
+ return snd_device;
+}
+#endif //DYNAMIC_ECNS_ENABLED
+
+snd_device_t platform_get_input_snd_device(void *platform,
+ struct stream_in *in,
+ audio_devices_t out_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
- audio_source_t source = (adev->active_input == NULL) ?
- AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
- audio_mode_t mode = adev->mode;
- audio_devices_t in_device = ((adev->active_input == NULL) ?
- AUDIO_DEVICE_NONE : adev->active_input->device)
- & ~AUDIO_DEVICE_BIT_IN;
- audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
- AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+ audio_mode_t mode = adev->mode;
snd_device_t snd_device = SND_DEVICE_NONE;
- int channel_count = popcount(channel_mask);
+
+ if (in == NULL) {
+ in = adev_get_active_input(adev);
+ }
+
+ audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+ audio_devices_t in_device =
+ ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+ audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+ int channel_count = audio_channel_count_from_in_mask(channel_mask);
ALOGV("%s: enter: out_device(%#x) in_device(%#x) channel_count (%d) channel_mask (0x%x)",
__func__, out_device, in_device, channel_count, channel_mask);
+
if ((out_device != AUDIO_DEVICE_NONE) && (voice_is_in_call(adev) ||
audio_extn_hfp_is_active(adev))) {
if (adev->voice.tty_mode != TTY_MODE_OFF) {
@@ -2970,6 +3303,8 @@
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
}
}
+ } else if (out_device & AUDIO_DEVICE_OUT_HEARING_AID) {
+ snd_device = SND_DEVICE_IN_VOICE_HEARING_AID;
}
} else if (source == AUDIO_SOURCE_CAMCORDER) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
@@ -3004,20 +3339,20 @@
if (my_data->fluence_in_voice_rec && channel_count == 1) {
if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
(my_data->source_mic_type & SOURCE_QUAD_MIC)) {
- if (adev->active_input->enable_aec)
+ if (in->enable_aec)
snd_device = SND_DEVICE_IN_HANDSET_QMIC_AEC;
else
snd_device = SND_DEVICE_IN_HANDSET_QMIC;
} else if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
(my_data->source_mic_type & SOURCE_THREE_MIC)) {
- if (adev->active_input->enable_aec)
+ if (in->enable_aec)
snd_device = SND_DEVICE_IN_HANDSET_TMIC_AEC;
else
snd_device = SND_DEVICE_IN_HANDSET_TMIC;
} else if (((my_data->fluence_type == FLUENCE_PRO_ENABLE) ||
(my_data->fluence_type == FLUENCE_ENABLE)) &&
(my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- if (adev->active_input->enable_aec)
+ if (in->enable_aec)
snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
else
snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
@@ -3034,14 +3369,14 @@
snd_device = SND_DEVICE_IN_QUAD_MIC;
}
if (snd_device == SND_DEVICE_NONE) {
- if (adev->active_input->enable_aec) {
- if (adev->active_input->enable_ns) {
+ if (in->enable_aec) {
+ if (in->enable_ns) {
snd_device = SND_DEVICE_IN_VOICE_REC_MIC_AEC_NS;
} else {
snd_device = SND_DEVICE_IN_VOICE_REC_MIC_AEC;
}
platform_set_echo_reference(adev, true, out_device);
- } else if (adev->active_input->enable_ns) {
+ } else if (in->enable_ns) {
snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
} else {
snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
@@ -3080,70 +3415,9 @@
!audio_extn_usb_is_capture_supported())) {
in_device = AUDIO_DEVICE_IN_BACK_MIC;
}
- if (adev->active_input) {
- if (adev->active_input->enable_aec &&
- adev->active_input->enable_ns) {
- if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_in_spkr_mode &&
- my_data->fluence_in_voice_comm &&
- (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
- } else {
- snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
- }
- } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->fluence_in_voice_comm &&
- (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
- } else {
- snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
- }
- } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
- snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
- } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
- snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
- }
- platform_set_echo_reference(adev, true, out_device);
- } else if (adev->active_input->enable_aec) {
- if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_in_spkr_mode &&
- my_data->fluence_in_voice_comm &&
- (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
- } else {
- snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
- }
- } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->fluence_in_voice_comm &&
- (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
- } else {
- snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
- }
- } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
- snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
- } else if (audio_is_usb_in_device(in_device | AUDIO_DEVICE_BIT_IN)) {
- snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
- }
- platform_set_echo_reference(adev, true, out_device);
- } else if (adev->active_input->enable_ns) {
- if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_in_spkr_mode &&
- my_data->fluence_in_voice_comm &&
- (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
- } else {
- snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
- }
- } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->fluence_in_voice_comm &&
- (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
- } else {
- snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
- }
- }
- }
+
+ if (in) {
+ snd_device = get_snd_device_for_voice_comm(my_data, in, out_device, in_device);
}
} else if (source == AUDIO_SOURCE_DEFAULT) {
goto exit;
@@ -3547,6 +3821,7 @@
case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
return DEEP_BUFFER_PLATFORM_DELAY;
case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
+ case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS:
return LOW_LATENCY_PLATFORM_DELAY;
case USECASE_AUDIO_PLAYBACK_ULL:
return ULL_PLATFORM_DELAY;
@@ -4743,7 +5018,7 @@
size_t actual_mic_count = 0;
snd_device_t active_input_snd_device =
- platform_get_input_snd_device(platform, usecase->stream.in->device);
+ platform_get_input_snd_device(platform, usecase->stream.in, AUDIO_DEVICE_NONE);
if (active_input_snd_device == SND_DEVICE_NONE) {
ALOGI("%s: No active microphones found", __func__);
goto end;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index f6c5a58..c2beec9 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -106,6 +106,7 @@
SND_DEVICE_OUT_VOICE_USB_HEADSET,
/* Specific snd_devices */
SND_DEVICE_OUT_USB_HEADSET_SPEC,
+ SND_DEVICE_OUT_VOICE_HEARING_AID,
SND_DEVICE_OUT_END,
/*
@@ -190,6 +191,9 @@
SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE,
SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE,
SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT,
+ SND_DEVICE_IN_SPEAKER_QMIC_NS,
+ SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS,
+ SND_DEVICE_IN_VOICE_HEARING_AID,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -287,6 +291,9 @@
#define LOWLATENCY_PCM_DEVICE 15
#define VOICE_VSID 0x10C01000
+#define AUDIO_HAPTICS_PCM_DEVICE 43
+#define HAPTICS_PCM_DEVICE 44
+
//needs verification
#define AUDIO_PLAYBACK_VOIP_PCM_DEVICE 5
#define AUDIO_RECORD_VOIP_PCM_DEVICE 6
@@ -343,6 +350,11 @@
#define HFP_ASM_RX_TX 24
#endif
+#define TX_VOICE_FLUENCE_PROV2 0x10F17
+#define TX_VOICE_DM_FV5_BROADSIDE 0x10F18
+#define TX_VOICE_FV5ECNS_SM 0x10F09
+#define TX_VOICE_FV5ECNS_DM 0x10F0A
+
#define LIB_CSD_CLIENT "libcsd-client.so"
#define LIB_MDM_DETECT "libmdmdetect.so"
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 1a7d2c3..1d46c31 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -27,6 +27,20 @@
#define SAMPLE_RATE_11025 11025
#define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
+typedef enum {
+ EFFECT_NONE = 0,
+ EFFECT_AEC,
+ EFFECT_NS,
+ EFFECT_COUNT
+} effect_type_t;
+
+struct audio_effect_config {
+ uint32_t module_id;
+ uint32_t instance_id;
+ uint32_t param_id;
+ uint32_t param_value;
+};
+
struct amp_db_and_gain_table {
float amp;
float db;
@@ -56,6 +70,12 @@
int platform_get_snd_device_index(char *snd_device_index_name);
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
int platform_get_snd_device_acdb_id(snd_device_t snd_device);
+int platform_set_effect_config_data(snd_device_t snd_device,
+ struct audio_effect_config effect_config,
+ effect_type_t effect_type);
+int platform_get_effect_config_data(snd_device_t snd_device,
+ struct audio_effect_config *effect_config,
+ effect_type_t effect_type);
int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
int platform_send_audio_calibration_v2(void *platform, struct audio_usecase *usecase,
int app_type, int sample_rate);
@@ -82,13 +102,18 @@
int platform_get_sample_rate(void *platform, uint32_t *rate);
int platform_set_device_mute(void *platform, bool state, char *dir);
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device);
+snd_device_t platform_get_input_snd_device(void *platform,
+ struct stream_in *in,
+ audio_devices_t out_device);
int platform_set_hdmi_channels(void *platform, int channel_count);
int platform_edid_get_max_channels(void *platform);
void platform_add_operator_specific_device(snd_device_t snd_device,
const char *operator,
const char *mixer_path,
unsigned int acdb_id);
+void platform_add_external_specific_device(snd_device_t snd_device,
+ const char *name,
+ unsigned int acdb_id);
/* return true if adding entry success
return false if adding entry fails */
@@ -117,11 +142,11 @@
bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id);
-/* From platform_info.c */
-int platform_info_init(const char *filename, void *);
-
typedef int (*set_parameters_fn)(void *platform, struct str_parms *parms);
-int snd_card_info_init(const char *filename, void *, set_parameters_fn);
+
+/* From platform_info.c */
+int platform_info_init(const char *filename, void *,
+ bool do_full_parse, set_parameters_fn);
int platform_get_usecase_index(const char * usecase);
int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
@@ -182,4 +207,9 @@
int platform_get_usb_service_interval(void *platform,
bool playback,
unsigned long *service_interval);
+int platform_get_haptics_pcm_device_id();
+
+/* callback functions from platform to common audio HAL */
+struct stream_in *adev_get_active_input(const struct audio_device *adev);
+
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index f5fbe3f..5159d6d 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -25,10 +25,22 @@
#include "platform_api.h"
#include <platform.h>
#include <math.h>
+#include <pthread.h>
+
+/*
+ * Mandatory microphone characteristics include: device_id, type, address, location, group,
+ * index_in_the_group, directionality, num_frequency_responses, frequencies and responses.
+ * MANDATORY_MICROPHONE_CHARACTERISTICS should be updated when mandatory microphone
+ * characteristics are changed.
+ */
+#define MANDATORY_MICROPHONE_CHARACTERISTICS (1 << 10) - 1
typedef enum {
ROOT,
ACDB,
+ MODULE,
+ AEC,
+ NS,
PCM_ID,
BACKEND_NAME,
CONFIG_PARAMS,
@@ -42,11 +54,15 @@
SND_DEV,
MIC_INFO,
ACDB_METAINFO_KEY,
+ EXTERNAL_DEVICE_SPECIFIC,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
static void process_acdb_id(const XML_Char **attr);
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type);
+static void process_effect_aec(const XML_Char **attr);
+static void process_effect_ns(const XML_Char **attr);
static void process_pcm_id(const XML_Char **attr);
static void process_backend_name(const XML_Char **attr);
static void process_config_params(const XML_Char **attr);
@@ -58,10 +74,13 @@
static void process_snd_dev(const XML_Char **attr);
static void process_mic_info(const XML_Char **attr);
static void process_acdb_metainfo_key(const XML_Char **attr);
+static void process_external_dev(const XML_Char **attr);
static section_process_fn section_table[] = {
[ROOT] = process_root,
[ACDB] = process_acdb_id,
+ [AEC] = process_effect_aec,
+ [NS] = process_effect_ns,
[PCM_ID] = process_pcm_id,
[BACKEND_NAME] = process_backend_name,
[CONFIG_PARAMS] = process_config_params,
@@ -72,19 +91,22 @@
[SND_DEV] = process_snd_dev,
[MIC_INFO] = process_mic_info,
[ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
+ [EXTERNAL_DEVICE_SPECIFIC] = process_external_dev,
};
-static set_parameters_fn set_parameters = &platform_set_parameters;
-
static section_t section;
struct platform_info {
+ pthread_mutex_t lock;
bool do_full_parse;
void *platform;
struct str_parms *kvpairs;
+ set_parameters_fn set_parameters;
};
-static struct platform_info my_data = {true, NULL, NULL};
+static struct platform_info my_data = {PTHREAD_MUTEX_INITIALIZER,
+ true, NULL, NULL,
+ &platform_set_parameters};
struct audio_string_to_enum {
const char* name;
@@ -145,17 +167,6 @@
AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
};
-enum {
- AUDIO_MICROPHONE_CHARACTERISTIC_NONE = 0u, // 0x0
- AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY = 1u, // 0x1
- AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL = 2u, // 0x2
- AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL = 4u, // 0x4
- AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION = 8u, // 0x8
- AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION = 16u, // 0x10
- AUDIO_MICROPHONE_CHARACTERISTIC_ALL = 31u, /* ((((SENSITIVITY | MAX_SPL) | MIN_SPL)
- | ORIENTATION) | GEOMETRIC_LOCATION) */
-};
-
static bool find_enum_by_string(const struct audio_string_to_enum * table, const char * name,
int32_t len, unsigned int *value)
{
@@ -185,6 +196,11 @@
* ...
* ...
* </acdb_ids>
+ * <module_ids>
+ * <device name="???" module_id="???"/>
+ * ...
+ * ...
+ * </module_ids>
* <backend_names>
* <device name="???" backend="???"/>
* ...
@@ -216,6 +232,77 @@
{
}
+static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type)
+{
+ int index;
+ struct audio_effect_config effect_config;
+
+ if (strncmp(attr[0], "name", strlen("name")) != 0) {
+ ALOGE("%s: 'name' not found, no MODULE ID set!", __func__);
+ goto done;
+ }
+
+ index = platform_get_snd_device_index((char *)attr[1]);
+ if (index < 0) {
+ ALOGE("%s: Device %s in platform info xml not found, no MODULE ID set!",
+ __func__, attr[1]);
+ goto done;
+ }
+
+ if (strncmp(attr[2], "module_id", strlen("module_id")) != 0) {
+ ALOGE("%s: Device %s in platform info xml has no module_id, no MODULE ID set!",
+ __func__, attr[2]);
+ goto done;
+ }
+
+ if (strncmp(attr[4], "instance_id", strlen("instance_id")) != 0) {
+ ALOGE("%s: Device %s in platform info xml has no instance_id, no INSTANCE ID set!",
+ __func__, attr[4]);
+ goto done;
+ }
+
+ if (strncmp(attr[6], "param_id", strlen("param_id")) != 0) {
+ ALOGE("%s: Device %s in platform info xml has no param_id, no PARAM ID set!",
+ __func__, attr[6]);
+ goto done;
+ }
+
+ if (strncmp(attr[8], "param_value", strlen("param_value")) != 0) {
+ ALOGE("%s: Device %s in platform info xml has no param_value, no PARAM VALUE set!",
+ __func__, attr[8]);
+ goto done;
+ }
+
+ effect_config = (struct audio_effect_config){strtol((char *)attr[3], NULL, 0),
+ strtol((char *)attr[5], NULL, 0),
+ strtol((char *)attr[7], NULL, 0),
+ strtol((char *)attr[9], NULL, 0)};
+
+
+ if (platform_set_effect_config_data(index, effect_config, effect_type) < 0) {
+ ALOGE("%s: Effect = %d Device %s, MODULE/INSTANCE/PARAM ID %u %u %u %u was not set!",
+ __func__, effect_type, attr[1], effect_config.module_id,
+ effect_config.instance_id, effect_config.param_id,
+ effect_config.param_value);
+ goto done;
+ }
+
+done:
+ return;
+}
+
+static void process_effect_aec(const XML_Char **attr)
+{
+ process_audio_effect(attr, EFFECT_AEC);
+ return;
+}
+
+static void process_effect_ns(const XML_Char **attr)
+{
+ process_audio_effect(attr, EFFECT_NS);
+ return;
+}
+
/* mapping from usecase to pcm dev id */
static void process_pcm_id(const XML_Char **attr)
{
@@ -404,6 +491,38 @@
return;
}
+static void process_external_dev(const XML_Char **attr)
+{
+ snd_device_t snd_device = SND_DEVICE_NONE;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found", __func__);
+ goto done;
+ }
+
+ snd_device = platform_get_snd_device_index((char *)attr[1]);
+ if (snd_device < 0) {
+ ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
+ __func__, (char *)attr[3], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "usbid") != 0) {
+ ALOGE("%s: 'usbid' not found", __func__);
+ goto done;
+ }
+
+ if (strcmp(attr[4], "acdb_id") != 0) {
+ ALOGE("%s: 'acdb_id' not found", __func__);
+ goto done;
+ }
+
+ platform_add_external_specific_device(snd_device, (char *)attr[3], atoi((char *)attr[5]));
+
+done:
+ return;
+}
+
/* platform specific configuration key-value pairs */
static void process_config_params(const XML_Char **attr)
{
@@ -418,7 +537,7 @@
}
str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
- set_parameters(my_data.platform, my_data.kvpairs);
+ my_data.set_parameters(my_data.platform, my_data.kvpairs);
done:
return;
}
@@ -458,221 +577,165 @@
static void process_microphone_characteristic(const XML_Char **attr) {
struct audio_microphone_characteristic_t microphone;
- uint32_t curIdx = 0;
+ uint32_t index = 0;
+ uint32_t found_mandatory_characteristics = 0;
+ uint32_t num_frequencies = 0;
+ uint32_t num_responses = 0;
+ microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+ microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ microphone.orientation.x = 0.0f;
+ microphone.orientation.y = 0.0f;
+ microphone.orientation.z = 0.0f;
+ microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
- if (strcmp(attr[curIdx++], "valid_mask")) {
- ALOGE("%s: valid_mask not found", __func__);
- goto done;
- }
- uint32_t valid_mask = atoi(attr[curIdx++]);
-
- if (strcmp(attr[curIdx++], "device_id")) {
- ALOGE("%s: device_id not found", __func__);
- goto done;
- }
- if (strlen(attr[curIdx]) > AUDIO_MICROPHONE_ID_MAX_LEN) {
- ALOGE("%s: device_id %s is too long", __func__, attr[curIdx]);
- goto done;
- }
- strcpy(microphone.device_id, attr[curIdx++]);
-
- if (strcmp(attr[curIdx++], "type")) {
- ALOGE("%s: device not found", __func__);
- goto done;
- }
- if (!find_enum_by_string(device_in_types, (char*)attr[curIdx++],
- ARRAY_SIZE(device_in_types), µphone.device)) {
- ALOGE("%s: type %s in %s not found!",
- __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
- goto done;
- }
-
- if (strcmp(attr[curIdx++], "address")) {
- ALOGE("%s: address not found", __func__);
- goto done;
- }
- if (strlen(attr[curIdx]) > AUDIO_DEVICE_MAX_ADDRESS_LEN) {
- ALOGE("%s, address %s is too long", __func__, attr[curIdx]);
- goto done;
- }
- strcpy(microphone.address, attr[curIdx++]);
- if (strlen(microphone.address) == 0) {
- // If the address is empty, populate the address according to device type.
- if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
- } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
- strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
- }
- }
-
- if (strcmp(attr[curIdx++], "location")) {
- ALOGE("%s: location not found", __func__);
- goto done;
- }
- if (!find_enum_by_string(mic_locations, (char*)attr[curIdx++],
- AUDIO_MICROPHONE_LOCATION_CNT, µphone.location)) {
- ALOGE("%s: location %s in %s not found!",
- __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
- goto done;
- }
-
- if (strcmp(attr[curIdx++], "group")) {
- ALOGE("%s: group not found", __func__);
- goto done;
- }
- microphone.group = atoi(attr[curIdx++]);
-
- if (strcmp(attr[curIdx++], "index_in_the_group")) {
- ALOGE("%s: index_in_the_group not found", __func__);
- goto done;
- }
- microphone.index_in_the_group = atoi(attr[curIdx++]);
-
- if (strcmp(attr[curIdx++], "directionality")) {
- ALOGE("%s: directionality not found", __func__);
- goto done;
- }
- if (!find_enum_by_string(mic_directionalities, (char*)attr[curIdx++],
- AUDIO_MICROPHONE_DIRECTIONALITY_CNT, µphone.directionality)) {
- ALOGE("%s: directionality %s in %s not found!",
- __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
- goto done;
- }
-
- if (strcmp(attr[curIdx++], "num_frequency_responses")) {
- ALOGE("%s: num_frequency_responses not found", __func__);
- goto done;
- }
- microphone.num_frequency_responses = atoi(attr[curIdx++]);
- if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
- ALOGE("%s: num_frequency_responses is too large", __func__);
- goto done;
- }
- if (microphone.num_frequency_responses > 0) {
- if (strcmp(attr[curIdx++], "frequencies")) {
- ALOGE("%s: frequencies not found", __func__);
- goto done;
- }
- char *token = strtok((char *)attr[curIdx++], " ");
- uint32_t num_frequencies = 0;
- while (token) {
- microphone.frequency_responses[0][num_frequencies++] = atof(token);
- if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
- ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
+ while (attr[index] != NULL) {
+ const char *attribute = attr[index++];
+ char value[strlen(attr[index]) + 1];
+ strcpy(value, attr[index++]);
+ if (strcmp(attribute, "device_id") == 0) {
+ if (strlen(value) > AUDIO_MICROPHONE_ID_MAX_LEN) {
+ ALOGE("%s: device_id %s is too long", __func__, value);
goto done;
}
- token = strtok(NULL, " ");
- }
-
- if (strcmp(attr[curIdx++], "responses")) {
- ALOGE("%s: responses not found", __func__);
- goto done;
- }
- token = strtok((char *)attr[curIdx++], " ");
- uint32_t num_responses = 0;
- while (token) {
- microphone.frequency_responses[1][num_responses++] = atof(token);
- if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
- ALOGE("%s: num %u of response is too large", __func__, num_responses);
+ strcpy(microphone.device_id, value);
+ found_mandatory_characteristics |= 1;
+ } else if (strcmp(attribute, "type") == 0) {
+ if (!find_enum_by_string(device_in_types, value,
+ ARRAY_SIZE(device_in_types), µphone.device)) {
+ ALOGE("%s: type %s in %s not found!",
+ __func__, value, PLATFORM_INFO_XML_PATH);
goto done;
}
- token = strtok(NULL, " ");
- }
-
- if (num_frequencies != num_responses
- || num_frequencies != microphone.num_frequency_responses) {
- ALOGE("%s: num of frequency and response not match: %u, %u, %u",
- __func__, num_frequencies, num_responses, microphone.num_frequency_responses);
- goto done;
- }
- }
-
- if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY) {
- if (strcmp(attr[curIdx++], "sensitivity")) {
- ALOGE("%s: sensitivity not found", __func__);
- goto done;
- }
- microphone.sensitivity = atof(attr[curIdx++]);
- } else {
- microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
- }
-
- if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL) {
- if (strcmp(attr[curIdx++], "max_spl")) {
- ALOGE("%s: max_spl not found", __func__);
- goto done;
- }
- microphone.max_spl = atof(attr[curIdx++]);
- } else {
- microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
- }
-
- if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL) {
- if (strcmp(attr[curIdx++], "min_spl")) {
- ALOGE("%s: min_spl not found", __func__);
- goto done;
- }
- microphone.min_spl = atof(attr[curIdx++]);
- } else {
- microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
- }
-
- if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION) {
- if (strcmp(attr[curIdx++], "orientation")) {
- ALOGE("%s: orientation not found", __func__);
- goto done;
- }
- char *token = strtok((char *)attr[curIdx++], " ");
- float orientation[3];
- uint32_t idx = 0;
- while (token) {
- orientation[idx++] = atof(token);
- if (idx > 3) {
+ found_mandatory_characteristics |= (1 << 1);
+ } else if (strcmp(attribute, "address") == 0) {
+ if (strlen(value) > AUDIO_DEVICE_MAX_ADDRESS_LEN) {
+ ALOGE("%s, address %s is too long", __func__, value);
+ goto done;
+ }
+ strcpy(microphone.address, value);
+ if (strlen(microphone.address) == 0) {
+ // If the address is empty, populate the address according to device type.
+ if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
+ strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
+ }
+ }
+ found_mandatory_characteristics |= (1 << 2);
+ } else if (strcmp(attribute, "location") == 0) {
+ if (!find_enum_by_string(mic_locations, value,
+ AUDIO_MICROPHONE_LOCATION_CNT, µphone.location)) {
+ ALOGE("%s: location %s in %s not found!",
+ __func__, value, PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+ found_mandatory_characteristics |= (1 << 3);
+ } else if (strcmp(attribute, "group") == 0) {
+ microphone.group = atoi(value);
+ found_mandatory_characteristics |= (1 << 4);
+ } else if (strcmp(attribute, "index_in_the_group") == 0) {
+ microphone.index_in_the_group = atoi(value);
+ found_mandatory_characteristics |= (1 << 5);
+ } else if (strcmp(attribute, "directionality") == 0) {
+ if (!find_enum_by_string(mic_directionalities, value,
+ AUDIO_MICROPHONE_DIRECTIONALITY_CNT, µphone.directionality)) {
+ ALOGE("%s: directionality %s in %s not found!",
+ __func__, attr[index], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+ found_mandatory_characteristics |= (1 << 6);
+ } else if (strcmp(attribute, "num_frequency_responses") == 0) {
+ microphone.num_frequency_responses = atoi(value);
+ if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("%s: num_frequency_responses is too large", __func__);
+ goto done;
+ }
+ found_mandatory_characteristics |= (1 << 7);
+ } else if (strcmp(attribute, "frequencies") == 0) {
+ char *token = strtok(value, " ");
+ while (token) {
+ microphone.frequency_responses[0][num_frequencies++] = atof(token);
+ if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+ found_mandatory_characteristics |= (1 << 8);
+ } else if (strcmp(attribute, "responses") == 0) {
+ char *token = strtok(value, " ");
+ while (token) {
+ microphone.frequency_responses[1][num_responses++] = atof(token);
+ if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("%s: num %u of response is too large", __func__, num_responses);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+ found_mandatory_characteristics |= (1 << 9);
+ } else if (strcmp(attribute, "sensitivity") == 0) {
+ microphone.sensitivity = atof(value);
+ } else if (strcmp(attribute, "max_spl") == 0) {
+ microphone.max_spl = atof(value);
+ } else if (strcmp(attribute, "min_spl") == 0) {
+ microphone.min_spl = atof(value);
+ } else if (strcmp(attribute, "orientation") == 0) {
+ char *token = strtok(value, " ");
+ float orientation[3];
+ uint32_t idx = 0;
+ while (token) {
+ orientation[idx++] = atof(token);
+ if (idx > 3) {
+ ALOGE("%s: orientation invalid", __func__);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+ if (idx != 3) {
ALOGE("%s: orientation invalid", __func__);
goto done;
}
- token = strtok(NULL, " ");
- }
- if (idx != 3) {
- ALOGE("%s: orientation invalid", __func__);
- goto done;
- }
- microphone.orientation.x = orientation[0];
- microphone.orientation.y = orientation[1];
- microphone.orientation.z = orientation[2];
- } else {
- microphone.orientation.x = 0.0f;
- microphone.orientation.y = 0.0f;
- microphone.orientation.z = 0.0f;
- }
-
- if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION) {
- if (strcmp(attr[curIdx++], "geometric_location")) {
- ALOGE("%s: geometric_location not found", __func__);
- goto done;
- }
- char *token = strtok((char *)attr[curIdx++], " ");
- float geometric_location[3];
- uint32_t idx = 0;
- while (token) {
- geometric_location[idx++] = atof(token);
- if (idx > 3) {
+ microphone.orientation.x = orientation[0];
+ microphone.orientation.y = orientation[1];
+ microphone.orientation.z = orientation[2];
+ } else if (strcmp(attribute, "geometric_location") == 0) {
+ char *token = strtok(value, " ");
+ float geometric_location[3];
+ uint32_t idx = 0;
+ while (token) {
+ geometric_location[idx++] = atof(token);
+ if (idx > 3) {
+ ALOGE("%s: geometric_location invalid", __func__);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+ if (idx != 3) {
ALOGE("%s: geometric_location invalid", __func__);
goto done;
}
- token = strtok(NULL, " ");
+ microphone.geometric_location.x = geometric_location[0];
+ microphone.geometric_location.y = geometric_location[1];
+ microphone.geometric_location.z = geometric_location[2];
+ } else {
+ ALOGW("%s: unknown attribute of microphone characteristics: %s",
+ __func__, attribute);
}
- if (idx != 3) {
- ALOGE("%s: geometric_location invalid", __func__);
- goto done;
- }
- microphone.geometric_location.x = geometric_location[0];
- microphone.geometric_location.y = geometric_location[1];
- microphone.geometric_location.z = geometric_location[2];
- } else {
- microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
- microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
- microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ }
+
+ if (num_frequencies != num_responses
+ || num_frequencies != microphone.num_frequency_responses) {
+ ALOGE("%s: num of frequency and response not match: %u, %u, %u",
+ __func__, num_frequencies, num_responses, microphone.num_frequency_responses);
+ goto done;
+ }
+
+ if (found_mandatory_characteristics != MANDATORY_MICROPHONE_CHARACTERISTICS) {
+ ALOGE("%s: some of mandatory microphone characteriscts are missed: %u",
+ __func__, found_mandatory_characteristics);
}
platform_set_microphone_characteristic(my_data.platform, microphone);
@@ -773,6 +836,8 @@
if (my_data.do_full_parse) {
if (strcmp(tag_name, "acdb_ids") == 0) {
section = ACDB;
+ } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) {
+ section = MODULE;
} else if (strcmp(tag_name, "pcm_ids") == 0) {
section = PCM_ID;
} else if (strcmp(tag_name, "backend_names") == 0) {
@@ -792,8 +857,9 @@
} else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
section = ACDB_METAINFO_KEY;
} else if (strcmp(tag_name, "device") == 0) {
- if ((section != ACDB) && (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
- ALOGE("device tag only supported for acdb/backend names");
+ if ((section != ACDB) && (section != AEC) && (section != NS) &&
+ (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
+ ALOGE("device tag only supported for acdb/backend/aec/ns/operator_specific names");
return;
}
@@ -869,6 +935,25 @@
}
section_process_fn fn = section_table[MIC_INFO];
fn(attr);
+ } else if (strcmp(tag_name, "external_specific_dev") == 0) {
+ section = EXTERNAL_DEVICE_SPECIFIC;
+ } else if (strcmp(tag_name, "ext_device") == 0) {
+ section_process_fn fn = section_table[section];
+ fn(attr);
+ }
+ else if (strncmp(tag_name, "aec", strlen("aec")) == 0) {
+ if (section != MODULE) {
+ ALOGE("aec tag only supported with MODULE section");
+ return;
+ }
+ section = AEC;
+ }
+ else if (strncmp(tag_name, "ns", strlen("ns")) == 0) {
+ if (section != MODULE) {
+ ALOGE("ns tag only supported with MODULE section");
+ return;
+ }
+ section = NS;
}
} else {
if(strcmp(tag_name, "config_params") == 0) {
@@ -891,6 +976,12 @@
{
if (strcmp(tag_name, "acdb_ids") == 0) {
section = ROOT;
+ } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) {
+ section = ROOT;
+ } else if (strncmp(tag_name, "aec", strlen("aec")) == 0) {
+ section = MODULE;
+ } else if (strncmp(tag_name, "ns", strlen("ns")) == 0) {
+ section = MODULE;
} else if (strcmp(tag_name, "pcm_ids") == 0) {
section = ROOT;
} else if (strcmp(tag_name, "backend_names") == 0) {
@@ -907,6 +998,8 @@
section = ROOT;
} else if (strcmp(tag_name, "snd_devices") == 0) {
section = ROOT;
+ } else if (strcmp(tag_name, "external_specific_dev") == 0) {
+ section = ROOT;
} else if (strcmp(tag_name, "input_snd_device") == 0) {
section = SND_DEVICES;
} else if (strcmp(tag_name, "input_snd_device_mic_mapping") == 0) {
@@ -916,14 +1009,8 @@
}
}
-int snd_card_info_init(const char *filename, void *platform, set_parameters_fn fn)
-{
- set_parameters = fn;
- my_data.do_full_parse = false;
- return platform_info_init(filename, platform);
-}
-
-int platform_info_init(const char *filename, void *platform)
+int platform_info_init(const char *filename, void *platform,
+ bool do_full_parse, set_parameters_fn fn)
{
XML_Parser parser;
FILE *file;
@@ -932,7 +1019,6 @@
void *buf;
static const uint32_t kBufSize = 1024;
char platform_info_file_name[MIXER_PATH_MAX_LENGTH]= {0};
- section = ROOT;
if (filename == NULL) {
strlcpy(platform_info_file_name, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
@@ -958,8 +1044,12 @@
goto err_close_file;
}
+ pthread_mutex_lock(&my_data.lock);
+ section = ROOT;
+ my_data.do_full_parse = do_full_parse;
my_data.platform = platform;
my_data.kvpairs = str_parms_create();
+ my_data.set_parameters = fn;
XML_SetElementHandler(parser, start_tag, end_tag);
@@ -990,10 +1080,12 @@
break;
}
- set_parameters = &platform_set_parameters;
- my_data.do_full_parse = true;
-
err_free_parser:
+ if (my_data.kvpairs != NULL) {
+ str_parms_destroy(my_data.kvpairs);
+ my_data.kvpairs = NULL;
+ }
+ pthread_mutex_unlock(&my_data.lock);
XML_ParserFree(parser);
err_close_file:
fclose(file);
diff --git a/hal/voice.c b/hal/voice.c
index 09cb926..708ce6c 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -171,6 +171,7 @@
uc_info->devices = adev->current_call_output ->devices;
uc_info->in_snd_device = SND_DEVICE_NONE;
uc_info->out_snd_device = SND_DEVICE_NONE;
+ adev->use_voice_device_mute = false;
list_add_tail(&adev->usecase_list, &uc_info->list);
@@ -357,11 +358,19 @@
int voice_set_mic_mute(struct audio_device *adev, bool state)
{
int err = 0;
+ struct audio_usecase *usecase = NULL;
adev->voice.mic_mute = state;
if (adev->mode == AUDIO_MODE_IN_CALL ||
- adev->mode == AUDIO_MODE_IN_COMMUNICATION)
- err = platform_set_mic_mute(adev->platform, state);
+ adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+ /* Use device mute if incall music delivery usecase is in progress */
+ if (adev->use_voice_device_mute)
+ err = platform_set_device_mute(adev->platform, state, "tx");
+ else
+ err = platform_set_mic_mute(adev->platform, state);
+ ALOGV("%s: voice mute status=%d, use_voice_device_mute_flag=%d",
+ __func__, state, adev->use_voice_device_mute);
+ }
return err;
}
@@ -371,6 +380,25 @@
return adev->voice.mic_mute;
}
+// Following function is called when incall music uplink usecase is
+// created or destroyed while mic is muted. If incall music uplink
+// usecase is active, apply voice device mute to mute only voice Tx
+// path and not the mixed voice Tx + inncall-music path. Revert to
+// voice stream mute once incall music uplink usecase is inactive
+void voice_set_device_mute_flag (struct audio_device *adev, bool state)
+{
+ if (adev->voice.mic_mute) {
+ if (state) {
+ platform_set_device_mute(adev->platform, true, "tx");
+ platform_set_mic_mute(adev->platform, false);
+ } else {
+ platform_set_mic_mute(adev->platform, true);
+ platform_set_device_mute(adev->platform, false, "tx");
+ }
+ }
+ adev->use_voice_device_mute = state;
+}
+
int voice_set_volume(struct audio_device *adev, float volume)
{
int vol, err = 0;
@@ -517,6 +545,8 @@
adev->voice.volume = 1.0f;
adev->voice.mic_mute = false;
adev->voice.in_call = false;
+ adev->use_voice_device_mute = false;
+
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
adev->voice.session[i].pcm_rx = NULL;
adev->voice.session[i].pcm_tx = NULL;
diff --git a/hal/voice.h b/hal/voice.h
index 469a3b5..71e096b 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -95,4 +95,6 @@
snd_device_t out_snd_device,
bool enable);
bool voice_is_call_state_active(struct audio_device *adev);
+void voice_set_device_mute_flag (struct audio_device *adev, bool state);
+
#endif //VOICE_H
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 9c658a3..ce84e41 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -1,4 +1,4 @@
-ifneq ($(filter msm8974 msm8226 msm8084 msm8992 msm8994 msm8996 msm8909 msm8998 sdm845 sdm710 sm8150,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8974 msm8226 msm8084 msm8992 msm8994 msm8996 msm8909 msm8998 sdm845 sdm710 msmnile,$(TARGET_BOARD_PLATFORM)),)
LOCAL_PATH:= $(call my-dir)
@@ -43,7 +43,7 @@
################################################################################
-ifneq ($(filter msm8992 msm8994 msm8996 msm8909 msm8998 sdm845 sdm710 sm8150,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8992 msm8994 msm8996 msm8909 msm8998 sdm845 sdm710 msmnile,$(TARGET_BOARD_PLATFORM)),)
include $(CLEAR_VARS)
diff --git a/post_proc/ma_listener.c b/post_proc/ma_listener.c
index 02d45d3..3074844 100644
--- a/post_proc/ma_listener.c
+++ b/post_proc/ma_listener.c
@@ -28,7 +28,7 @@
#include <audio-base.h>
#define MA_FLAG ( EFFECT_FLAG_TYPE_INSERT | \
- EFFECT_FLAG_VOLUME_IND | \
+ EFFECT_FLAG_VOLUME_MONITOR | \
EFFECT_FLAG_DEVICE_IND | \
EFFECT_FLAG_OFFLOAD_SUPPORTED | \
EFFECT_FLAG_NO_PROCESS)