Merge "hal: add single session VSID voice call support"
diff --git a/hal/Android.mk b/hal/Android.mk
index 9fa30c6..99b6b39 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -194,6 +194,11 @@
LOCAL_CFLAGS += -DHDMI_PASSTHROUGH_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SOURCE_TRACKING)),true)
+ LOCAL_CFLAGS += -DSOURCE_TRACKING_ENABLED
+ LOCAL_SRC_FILES += audio_extn/source_track.c
+endif
+
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index de51542..688e265 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -91,6 +91,17 @@
struct str_parms *parms);
#endif
+#ifndef SOURCE_TRACKING_ENABLED
+#define audio_extn_source_track_set_parameters(adev, parms) (0)
+#define audio_extn_source_track_get_parameters(adev, query, reply) (0)
+#else
+void audio_extn_source_track_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+void audio_extn_source_track_get_parameters(struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply);
+#endif
+
#ifndef CUSTOM_STEREO_ENABLED
#define audio_extn_customstereo_set_parameters(adev, parms) (0)
#else
@@ -535,6 +546,7 @@
audio_extn_customstereo_set_parameters(adev, parms);
audio_extn_hpx_set_parameters(adev, parms);
audio_extn_pm_set_parameters(parms);
+ audio_extn_source_track_set_parameters(adev, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -547,6 +559,7 @@
get_active_offload_usecases(adev, query, reply);
audio_extn_dts_eagle_get_parameters(adev, query, reply);
audio_extn_hpx_get_parameters(query, reply);
+ audio_extn_source_track_get_parameters(adev, query, reply);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
index 83c3506..52d7abb 100644
--- a/hal/audio_extn/dts_eagle.c
+++ b/hal/audio_extn/dts_eagle.c
@@ -150,20 +150,16 @@
if (strncmp("true", prop, sizeof("true")))
return;
int fd, n = 0;
- if ((fd = open(FADE_NOTIFY_FILE, O_RDONLY)) < 0)
- ALOGV("No fade node");
- else {
- ALOGV("fade node exists, remove it before creating it");
- close(fd);
- remove(FADE_NOTIFY_FILE);
+ if ((fd = open(FADE_NOTIFY_FILE, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGV("No fade node, create one");
+ fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd < 0) {
+ ALOGE("DTS_EAGLE_HAL (%s): Creating fade notifier node failed", __func__);
+ return;
+ }
+ chmod(FADE_NOTIFY_FILE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
}
- fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
char *str = need_data ? "need" : "have";
- if (fd < 0) {
- ALOGE("DTS_EAGLE_HAL (%s): opening fade notifier node failed", __func__);
- return;
- }
- chmod(FADE_NOTIFY_FILE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
n = write(fd, str, strlen(str));
close(fd);
if (n > 0)
diff --git a/hal/audio_extn/source_track.c b/hal/audio_extn/source_track.c
new file mode 100644
index 0000000..316e52d
--- /dev/null
+++ b/hal/audio_extn/source_track.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "source_track"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <errno.h>
+#include <math.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "voice_extn.h"
+#include <stdlib.h>
+#include <cutils/str_parms.h>
+
+#ifdef SOURCE_TRACKING_ENABLED
+/* Audio Paramater Key to identify the list of start angles.
+ * Starting angle (in degrees) defines the boundary starting angle for each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES "SoundFocus.start_angles"
+/* Audio Paramater Key to identify the list of enable flags corresponding to each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS "SoundFocus.enable_sectors"
+/* Audio Paramater Key to identify the gain step value to be applied to all enabled sectors.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP "SoundFocus.gain_step"
+/* Audio Paramater Key to identify the list of voice activity detector outputs corresponding
+ * to each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD "SourceTrack.vad"
+/* Audio Paramater Key to identify the direction (in degrees) of arrival for desired talker
+ * (dominant source of speech).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH "SourceTrack.doa_speech"
+/* Audio Paramater Key to identify the list of directions (in degrees) of arrival for
+ * interferers (interfering noise sources).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE "SourceTrack.doa_noise"
+/* Audio Paramater Key to identify the list of sound strength indicators at each degree
+ * of the horizontal plane referred to by a full circle (360 degrees).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY "SourceTrack.polar_activity"
+
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES 0x1
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS 0x2
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP 0x4
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD 0x8
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH 0x10
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE 0x20
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY 0x40
+
+#define BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS \
+ (BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
+
+#define BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING \
+ (BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY)
+
+#define MAX_SECTORS 8
+#define MAX_STR_SIZE 2048
+
+struct audio_device_to_audio_interface audio_device_to_interface_table[];
+int audio_device_to_interface_table_len;
+
+struct sound_focus_param {
+ uint16_t start_angle[MAX_SECTORS];
+ uint8_t enable[MAX_SECTORS];
+ uint16_t gain_step;
+};
+
+struct source_tracking_param {
+ uint8_t vad[MAX_SECTORS];
+ uint16_t doa_speech;
+ uint16_t doa_noise[3];
+ uint8_t polar_activity[360];
+};
+
+static int add_audio_intf_name_to_mixer_ctl(audio_devices_t device, char *mixer_ctl_name,
+ struct audio_device_to_audio_interface *table, int len)
+{
+ int ret = 0;
+ int i;
+
+ if (table == NULL) {
+ ALOGE("%s: table is NULL", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (mixer_ctl_name == NULL) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ for (i=0; i < len; i++) {
+ if (device == table[i].device) {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, table[i].interface_name, MIXER_PATH_MAX_LENGTH);
+ break;
+ }
+ }
+
+ if (i == len) {
+ ALOGE("%s: Audio Device not found in the table", __func__);
+
+ ret = -EINVAL;
+ }
+done:
+ return ret;
+}
+
+static bool is_stt_supported_snd_device(snd_device_t snd_device)
+{
+ bool ret = false;
+
+ switch (snd_device) {
+ case SND_DEVICE_IN_HANDSET_DMIC:
+ case SND_DEVICE_IN_HANDSET_DMIC_AEC:
+ case SND_DEVICE_IN_HANDSET_DMIC_NS:
+ case SND_DEVICE_IN_HANDSET_DMIC_AEC_NS:
+ case SND_DEVICE_IN_HANDSET_STEREO_DMIC:
+ case SND_DEVICE_IN_HANDSET_QMIC:
+ case SND_DEVICE_IN_VOICE_DMIC:
+ case SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE:
+ case SND_DEVICE_IN_HEADSET_MIC_FLUENCE:
+ case SND_DEVICE_IN_SPEAKER_DMIC:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC:
+ case SND_DEVICE_IN_SPEAKER_DMIC_NS:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE:
+ case SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE:
+ case SND_DEVICE_IN_SPEAKER_QMIC_AEC:
+ case SND_DEVICE_IN_SPEAKER_QMIC_NS:
+ case SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS:
+ case SND_DEVICE_IN_VOICE_SPEAKER_DMIC:
+ case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE:
+ case SND_DEVICE_IN_VOICE_SPEAKER_QMIC:
+ ret = true;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+audio_devices_t get_input_audio_device(audio_devices_t device)
+{
+ audio_devices_t in_device = device;
+
+ switch (device) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ break;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ in_device = AUDIO_DEVICE_IN_BACK_MIC;
+ break;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ in_device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ break;
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ in_device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ break;
+ default:
+ break;
+ }
+
+ return in_device;
+}
+
+static int derive_mixer_ctl_from_usecase_intf(struct audio_device *adev,
+ char *mixer_ctl_name) {
+ struct audio_usecase *usecase = NULL;
+ audio_devices_t in_device;
+ int ret = 0;
+
+ if (mixer_ctl_name == NULL) {
+ ALOGE("%s: mixer_ctl_name is NULL", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (voice_is_in_call(adev)) {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
+ usecase = get_usecase_from_list(adev,
+ get_usecase_id_from_usecase_type(adev, VOICE_CALL));
+ } else if (voice_extn_compress_voip_is_active(adev)) {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
+ usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
+ } else {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, "Audio Tx", MIXER_PATH_MAX_LENGTH);
+ usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, PCM_CAPTURE));
+ }
+
+ if (usecase && (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
+ if (is_stt_supported_snd_device(usecase->in_snd_device)) {
+ in_device = get_input_audio_device(usecase->devices);
+ ret = add_audio_intf_name_to_mixer_ctl(in_device, mixer_ctl_name,
+ audio_device_to_interface_table, audio_device_to_interface_table_len);
+ } else {
+ ALOGE("%s: Sound Focus/Source Tracking not supported on the input sound device (%s)",
+ __func__, platform_get_snd_device_name(usecase->in_snd_device));
+
+ ret = -EINVAL;
+ }
+ } else {
+ ALOGE("%s: No use case is active which supports Sound Focus/Source Tracking",
+ __func__);
+
+ ret = -EINVAL;
+ }
+
+done:
+ return ret;
+}
+
+static int parse_soundfocus_sourcetracking_keys(struct str_parms *parms)
+{
+ char *str;
+ char *value = NULL;
+ int val, len;
+ int ret = 0, err;
+ char *kv_pairs = str_parms_to_str(parms);
+
+ ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
+
+ len = strlen(kv_pairs);
+ value = (char*)calloc(len, sizeof(char));
+ if(value == NULL) {
+ ret = -ENOMEM;
+ ALOGE("%s: failed to allocate memory", __func__);
+
+ goto done;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY;
+ }
+
+done:
+ free(kv_pairs);
+ if(value != NULL)
+ free(value);
+ ALOGV("%s: returning bitmask = %d", __func__, ret);
+
+ return ret;
+}
+
+static int get_soundfocus_sourcetracking_data(struct audio_device *adev,
+ const int bitmask,
+ struct sound_focus_param *sound_focus_data,
+ struct source_tracking_param *source_tracking_data)
+{
+ struct mixer_ctl *ctl;
+ char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
+ char source_tracking_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Source Tracking";
+ int ret = -EINVAL;
+ int i, count;
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS) {
+ /* Derive the mixer control name based on the use case and the audio interface
+ * for the corresponding audio device
+ */
+ ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
+ if (ret != 0) {
+ ALOGE("%s: Could not get Sound Focus Params", __func__);
+
+ goto done;
+ } else {
+ ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, sound_focus_mixer_ctl_name);
+
+ ret = -EINVAL;
+ goto done;
+ } else {
+ ALOGV("%s: Getting Sound Focus Params", __func__);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct sound_focus_param)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid sound focus data size", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)sound_focus_data, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_get_array() failed to get Sound Focus Params", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+ }
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING) {
+ /* Derive the mixer control name based on the use case and the audio interface
+ * for the corresponding audio device
+ */
+ ret = derive_mixer_ctl_from_usecase_intf(adev, source_tracking_mixer_ctl_name);
+ if (ret != 0) {
+ ALOGE("%s: Could not get Source Tracking Params", __func__);
+
+ goto done;
+ } else {
+ ALOGV("%s: Mixer Ctl name: %s", __func__, source_tracking_mixer_ctl_name);
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, source_tracking_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, source_tracking_mixer_ctl_name);
+
+ ret = -EINVAL;
+ goto done;
+ } else {
+ ALOGV("%s: Getting Source Tracking Params", __func__);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct source_tracking_param)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid source tracking data size", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)source_tracking_data, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_get_array() failed to get Source Tracking Params", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+ }
+
+done:
+ return ret;
+}
+
+static void send_soundfocus_sourcetracking_params(struct str_parms *reply,
+ const int bitmask,
+ const struct sound_focus_param sound_focus_data,
+ const struct source_tracking_param source_tracking_data)
+{
+ int i = 0, len = 0;
+ char value[MAX_STR_SIZE] = "";
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES) {
+ for (i = 0; i < MAX_SECTORS; i++) {
+ if ((i >=4) && (sound_focus_data.start_angle[i] == 0xFFFF))
+ continue;
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.start_angle[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value);
+ }
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS) {
+ for (i = 0; i < MAX_SECTORS; i++) {
+ if ((i >=4) && (sound_focus_data.enable[i] == 0xFF))
+ continue;
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.enable[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value);
+ }
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, sound_focus_data.gain_step);
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD) {
+ for (i = 0; i < MAX_SECTORS; i++) {
+ if ((i >=4) && (source_tracking_data.vad[i] == 0xFF))
+ continue;
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.vad[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value);
+ }
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH)
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, source_tracking_data.doa_speech);
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE) {
+ snprintf(value, MAX_STR_SIZE,
+ "%d,%d,%d", source_tracking_data.doa_noise[0], source_tracking_data.doa_noise[1], source_tracking_data.doa_noise[2]);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value);
+ }
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) {
+ for (i = 0; i < 360; i++) {
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.polar_activity[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value);
+ }
+}
+
+void audio_extn_source_track_get_parameters(struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply)
+{
+ int bitmask = 0, ret = 0;
+ struct sound_focus_param sound_focus_data;
+ struct source_tracking_param source_tracking_data;
+
+ memset(&sound_focus_data, 0xFF, sizeof(struct sound_focus_param));
+ memset(&source_tracking_data, 0xFF, sizeof(struct source_tracking_param));
+
+ // Parse the input parameters string for Source Tracking keys
+ bitmask = parse_soundfocus_sourcetracking_keys(query);
+ if (bitmask) {
+ // Get the parameter values from the backend
+ ret = get_soundfocus_sourcetracking_data(adev, bitmask, &sound_focus_data, &source_tracking_data);
+ if (ret == 0) {
+ // Construct the return string with key, value pairs
+ send_soundfocus_sourcetracking_params(reply, bitmask, sound_focus_data, source_tracking_data);
+ }
+ }
+}
+
+void audio_extn_source_track_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int len, ret, count;;
+ struct mixer_ctl *ctl;
+ char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
+ char *value = NULL;
+ char *kv_pairs = str_parms_to_str(parms);
+
+ len = strlen(kv_pairs);
+ value = (char*)calloc(len, sizeof(char));
+ if(value == NULL) {
+ ret = -ENOMEM;
+ ALOGE("%s: failed to allocate memory", __func__);
+
+ goto done;
+ }
+
+ // Parse the input parameter string for Source Tracking key, value pairs
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
+ value, len);
+ if (ret >= 0) {
+ char *saveptr, *tok;
+ int i = 0, val;
+ struct sound_focus_param sound_focus_param;
+
+ memset(&sound_focus_param, 0xFF, sizeof(struct sound_focus_param));
+
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
+ tok = strtok_r(value, ",", &saveptr);
+ while ((i < MAX_SECTORS) && (tok != NULL)) {
+ if (sscanf(tok, "%d", &val) == 1) {
+ sound_focus_param.start_angle[i++] = (uint16_t)val;
+ }
+ tok = strtok_r(NULL, ",", &saveptr);
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
+ value, len);
+ if (ret >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
+ tok = strtok_r(value, ",", &saveptr);
+ i = 0;
+ while ((i < MAX_SECTORS) && (tok != NULL)) {
+ if (sscanf(tok, "%d", &val) == 1) {
+ sound_focus_param.enable[i++] = (uint8_t)val;
+ }
+ tok = strtok_r(NULL, ",", &saveptr);
+ }
+ } else {
+ ALOGE("%s: SoundFocus.enable_sectors key not found", __func__);
+
+ goto done;
+ }
+
+ ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, &val);
+ if (ret >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
+ sound_focus_param.gain_step = (uint16_t)val;
+ } else {
+ ALOGE("%s: SoundFocus.gain_step key not found", __func__);
+
+ goto done;
+ }
+
+ /* Derive the mixer control name based on the use case and the audio h/w
+ * interface name for the corresponding audio device
+ */
+ ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
+ if (ret != 0) {
+ ALOGE("%s: Could not set Sound Focus Params", __func__);
+
+ goto done;
+ } else {
+ ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, sound_focus_mixer_ctl_name);
+
+ goto done;
+ } else {
+ ALOGV("%s: Setting Sound Focus Params", __func__);
+
+ for (i = 0; i < MAX_SECTORS;i++) {
+ ALOGV("%s: start_angles[%d] = %d", __func__, i, sound_focus_param.start_angle[i]);
+ }
+ for (i = 0; i < MAX_SECTORS;i++) {
+ ALOGV("%s: enable_sectors[%d] = %d", __func__, i, sound_focus_param.enable[i]);
+ }
+ ALOGV("%s: gain_step = %d", __func__, sound_focus_param.gain_step);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct sound_focus_param)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid data size", __func__);
+
+ goto done;
+ }
+
+ // Set the parameters on the mixer control derived above
+ ret = mixer_ctl_set_array(ctl, (void *)&sound_focus_param, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_set_array() failed to set Sound Focus Params", __func__);
+
+ goto done;
+ }
+ }
+ }
+
+done:
+ free(kv_pairs);
+ if(value != NULL)
+ free(value);
+ return;
+}
+#endif /* SOURCE_TRACKING_ENABLED end */
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 70ce471..138bd3c 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -287,7 +287,9 @@
format == AUDIO_FORMAT_AAC_HE_V2 ||
format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
- format == AUDIO_FORMAT_FLAC)
+ format == AUDIO_FORMAT_FLAC ||
+ format == AUDIO_FORMAT_WMA ||
+ format == AUDIO_FORMAT_WMA_PRO)
return true;
return false;
@@ -310,6 +312,12 @@
case AUDIO_FORMAT_FLAC:
id = SND_AUDIOCODEC_FLAC;
break;
+ case AUDIO_FORMAT_WMA:
+ id = SND_AUDIOCODEC_WMA;
+ break;
+ case AUDIO_FORMAT_WMA_PRO:
+ id = SND_AUDIOCODEC_WMA_PRO;
+ break;
default:
ALOGE("%s: Unsupported audio format :%x", __func__, format);
}
@@ -742,14 +750,15 @@
return ret;
}
-static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
+audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
+ usecase_type_t type)
{
struct audio_usecase *usecase;
struct listnode *node;
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == VOICE_CALL) {
+ if (usecase->type == type) {
ALOGV("%s: usecase id %d", __func__, usecase->id);
return usecase->id;
}
@@ -806,7 +815,7 @@
*/
if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
vc_usecase = get_usecase_from_list(adev,
- get_voice_usecase_id_from_list(adev));
+ get_usecase_id_from_usecase_type(adev, VOICE_CALL));
if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
(usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
in_snd_device = vc_usecase->in_snd_device;
@@ -1799,6 +1808,52 @@
}
}
+ if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->format = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.super_block_align = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.channelmask = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+ out->compr_config.codec->format,
+ out->compr_config.codec->options.wma.super_block_align,
+ out->compr_config.codec->options.wma.bits_per_sample,
+ out->compr_config.codec->options.wma.channelmask,
+ out->compr_config.codec->options.wma.encodeopt,
+ out->compr_config.codec->options.wma.encodeopt1,
+ out->compr_config.codec->options.wma.encodeopt2);
+ }
+
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
if(ret >= 0)
is_meta_data_params = true;
@@ -2134,6 +2189,7 @@
}
if (!out->playback_started && ret >= 0) {
compress_start(out->compr);
+ audio_extn_dts_eagle_fade(adev, true, out);
out->playback_started = 1;
out->offload_state = OFFLOAD_STATE_PLAYING;
@@ -3366,7 +3422,7 @@
struct audio_stream_in **stream_in,
audio_input_flags_t flags __unused,
const char *address __unused,
- audio_source_t source __unused)
+ audio_source_t source)
{
struct audio_device *adev = (struct audio_device *)dev;
struct stream_in *in;
@@ -3386,8 +3442,8 @@
}
ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
- stream_handle(%p) io_handle(%d)",__func__, config->sample_rate, config->channel_mask,
- devices, &in->stream, handle);
+ stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
+ devices, &in->stream, handle, source);
pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
@@ -3408,7 +3464,7 @@
in->stream.get_input_frames_lost = in_get_input_frames_lost;
in->device = devices;
- in->source = AUDIO_SOURCE_DEFAULT;
+ in->source = source;
in->dev = adev;
in->standby = 1;
in->channel_mask = config->channel_mask;
@@ -3474,6 +3530,13 @@
channel_count,
is_low_latency);
in->config.period_size = buffer_size / frame_size;
+ if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
+ (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
+ (voice_extn_compress_voip_is_format_supported(in->format)) &&
+ (in->config.rate == 8000 || in->config.rate == 16000) &&
+ (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
+ voice_extn_compress_voip_open_input_stream(in);
+ }
}
/* This stream could be for sound trigger lab,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 5807377..67f5279 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -344,6 +344,8 @@
int pcm_ioctl(struct pcm *pcm, int request, ...);
int get_snd_card_state(struct audio_device *adev);
+audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
+ usecase_type_t type);
#define LITERAL_TO_STRING(x) #x
#define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
old mode 100755
new mode 100644
index cfca1d5..1ebff09
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -3943,3 +3943,9 @@
strlcpy(buf, PLATFORM_IMAGE_NAME, sizeof(PLATFORM_IMAGE_NAME));
return 0;
}
+
+int platform_set_audio_device_interface(const char * device_name __unused,
+ const char *intf_name __unused)
+{
+ return -ENOSYS;
+}
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index c37fab7..7e87a3c 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -243,7 +243,7 @@
#define VOICE_CALL_PCM_DEVICE 2
#define VOICE2_CALL_PCM_DEVICE 13
#define VOLTE_CALL_PCM_DEVICE 15
-#define QCHAT_CALL_PCM_DEVICE 14
+#define QCHAT_CALL_PCM_DEVICE 26
#define VOWLAN_CALL_PCM_DEVICE 16
#define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 4c798b6..bbfa042 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -1153,3 +1153,9 @@
{
return 0;
}
+
+int platform_set_audio_device_interface(const char * device_name __unused,
+ const char *intf_name __unused)
+{
+ return -ENOSYS;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index ff2d021..cd4019e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -641,6 +641,32 @@
{AUDIO_DEVICE_NONE , -1},
{AUDIO_DEVICE_OUT_DEFAULT , -1},
};
+#elif PLATFORM_MSM8996
+static int msm_device_to_be_id [][NO_COLS] = {
+ {AUDIO_DEVICE_OUT_EARPIECE , 2},
+ {AUDIO_DEVICE_OUT_SPEAKER , 2},
+ {AUDIO_DEVICE_OUT_WIRED_HEADSET , 2},
+ {AUDIO_DEVICE_OUT_WIRED_HEADPHONE , 2},
+ {AUDIO_DEVICE_OUT_BLUETOOTH_SCO , 11},
+ {AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET , 11},
+ {AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT , 11},
+ {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP , -1},
+ {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES , -1},
+ {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER , -1},
+ {AUDIO_DEVICE_OUT_AUX_DIGITAL , 4},
+ {AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET , 9},
+ {AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET , 9},
+ {AUDIO_DEVICE_OUT_USB_ACCESSORY , -1},
+ {AUDIO_DEVICE_OUT_USB_DEVICE , -1},
+ {AUDIO_DEVICE_OUT_REMOTE_SUBMIX , 9},
+ {AUDIO_DEVICE_OUT_PROXY , 9},
+/* Add the correct be ids */
+ {AUDIO_DEVICE_OUT_FM , 7},
+ {AUDIO_DEVICE_OUT_FM_TX , 8},
+ {AUDIO_DEVICE_OUT_ALL , -1},
+ {AUDIO_DEVICE_NONE , -1},
+ {AUDIO_DEVICE_OUT_DEFAULT , -1},
+};
#else
static int msm_device_to_be_id [][NO_COLS] = {
{AUDIO_DEVICE_NONE, -1},
@@ -3668,3 +3694,54 @@
end:
return ret;
}
+
+/*
+ * This is a lookup table to map android audio input device to audio h/w interface (backend).
+ * The table can be extended for other input devices by adding appropriate entries.
+ * Also the audio interface for a particular input device can be overriden by adding
+ * corresponding entry in audio_platform_info.xml file.
+ */
+struct audio_device_to_audio_interface audio_device_to_interface_table[] = {
+ {AUDIO_DEVICE_IN_BUILTIN_MIC, ENUM_TO_STRING(AUDIO_DEVICE_IN_BUILTIN_MIC), "SLIMBUS_0"},
+ {AUDIO_DEVICE_IN_BACK_MIC, ENUM_TO_STRING(AUDIO_DEVICE_IN_BACK_MIC), "SLIMBUS_0"},
+};
+
+int audio_device_to_interface_table_len =
+ sizeof(audio_device_to_interface_table) / sizeof(audio_device_to_interface_table[0]);
+
+int platform_set_audio_device_interface(const char *device_name, const char *intf_name)
+{
+ int ret = 0;
+ int i;
+
+ if (device_name == NULL || intf_name == NULL) {
+ ALOGE("%s: Invalid input", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGD("%s: Enter, device name:%s, intf name:%s", __func__, device_name, intf_name);
+
+ size_t device_name_len = strlen(device_name);
+ for (i = 0; i < audio_device_to_interface_table_len; i++) {
+ char* name = audio_device_to_interface_table[i].device_name;
+ size_t name_len = strlen(name);
+ if ((name_len == device_name_len) &&
+ (strncmp(device_name, name, name_len) == 0)) {
+ ALOGD("%s: Matched device name:%s, overwrite intf name with %s",
+ __func__, device_name, intf_name);
+
+ strlcpy(audio_device_to_interface_table[i].interface_name, intf_name,
+ sizeof(audio_device_to_interface_table[i].interface_name));
+ goto done;
+ }
+ }
+ ALOGE("%s: Could not find matching device name %s",
+ __func__, device_name);
+
+ ret = -EINVAL;
+
+done:
+ return ret;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index f10ea5f..83922d5 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -374,4 +374,12 @@
*/
#define DEVICE_PARAM_MUTE_ID 0
#define DEVICE_PARAM_LATENCY_ID 1
+
+#define ENUM_TO_STRING(X) #X
+
+struct audio_device_to_audio_interface {
+ audio_devices_t device;
+ char device_name[100];
+ char interface_name[100];
+};
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 3e81d68..3808b14 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -109,4 +109,5 @@
void platform_invalidate_edid(void * platform);
int platform_set_hdmi_config(struct stream_out *out);
int platform_set_device_params(struct stream_out *out, int param, int value);
+int platform_set_audio_device_interface(const char * device_name, const char *intf_name);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index a176177..13a314e 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -46,6 +46,7 @@
BITWIDTH,
PCM_ID,
BACKEND_NAME,
+ INTERFACE_NAME,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
@@ -54,6 +55,7 @@
static void process_bit_width(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_interface_name(const XML_Char **attr);
static void process_root(const XML_Char **attr);
static section_process_fn section_table[] = {
@@ -62,6 +64,7 @@
[BITWIDTH] = process_bit_width,
[PCM_ID] = process_pcm_id,
[BACKEND_NAME] = process_backend_name,
+ [INTERFACE_NAME] = process_interface_name,
};
static section_t section;
@@ -83,6 +86,11 @@
* ...
* ...
* </pcm_ids>
+ * <interface_names>
+ * <device name="Use audio device name here, not sound device name" interface="PRIMARY_I2S"/>
+ * ...
+ * ...
+ * </interface_names>
* </audio_platform_info>
*/
@@ -237,6 +245,34 @@
return;
}
+static void process_interface_name(const XML_Char **attr)
+{
+ int ret;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found, no Audio Interface set!", __func__);
+
+ goto done;
+ }
+
+ if (strcmp(attr[2], "interface") != 0) {
+ ALOGE("%s: Device %s has no Audio Interface set!",
+ __func__, attr[1]);
+
+ goto done;
+ }
+
+ ret = platform_set_audio_device_interface((char *)attr[1], (char *)attr[3]);
+ if (ret < 0) {
+ ALOGE("%s: Audio Interface not set!", __func__);
+
+ goto done;
+ }
+
+done:
+ return;
+}
+
static void start_tag(void *userdata __unused, const XML_Char *tag_name,
const XML_Char **attr)
{
@@ -252,9 +288,12 @@
section = PCM_ID;
} else if (strcmp(tag_name, "backend_names") == 0) {
section = BACKEND_NAME;
+ } else if (strcmp(tag_name, "interface_names") == 0) {
+ section = INTERFACE_NAME;
} else if (strcmp(tag_name, "device") == 0) {
- if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH)) {
- ALOGE("device tag only supported for acdb/backend names");
+ if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
+ (section != INTERFACE_NAME)) {
+ ALOGE("device tag only supported for acdb/backend names/bitwitdh/interface names");
return;
}
@@ -284,6 +323,8 @@
section = ROOT;
} else if (strcmp(tag_name, "backend_names") == 0) {
section = ROOT;
+ } else if (strcmp(tag_name, "interface_names") == 0) {
+ section = ROOT;
}
}
diff --git a/hal/voice.c b/hal/voice.c
index 01158dd..9fc1081 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -157,6 +157,8 @@
}
ALOGD("voice_config.rate %d\n", voice_config.rate);
+ voice_set_mic_mute(adev, adev->voice.mic_mute);
+
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
__func__, adev->snd_card, pcm_dev_rx_id);
session->pcm_rx = pcm_open(adev->snd_card,
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index e8ba1f9..14af6fc 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -697,6 +697,10 @@
voip_data.sample_rate = in->config.rate;
}
+ ret = voip_set_mode(in->dev, in->format);
+ if (ret < 0)
+ goto done;
+
in->usecase = USECASE_COMPRESS_VOIP_CALL;
if (in->config.rate == 16000)
in->config = pcm_config_voip_wb;
@@ -704,7 +708,6 @@
in->config = pcm_config_voip_nb;
voip_data.in_stream_count++;
- ret = voip_set_mode(in->dev, in->format);
done:
ALOGV("%s: exit, ret=%d", __func__, ret);
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 880838a..be70166 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -26,7 +26,8 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
- libtinyalsa
+ libtinyalsa \
+ libdl
LOCAL_MODULE_TAGS := optional
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index 57cf8ef..ad1e7c9 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -17,14 +17,17 @@
* limitations under the License.
*/
-#define LOG_TAG "offload_effect_bass_boost"
+#define LOG_TAG "offload_effect_bass"
//#define LOG_NDEBUG 0
#include <cutils/list.h>
#include <cutils/log.h>
+#include <cutils/properties.h>
#include <tinyalsa/asoundlib.h>
#include <sound/audio_effects.h>
#include <audio_effects/effect_bassboost.h>
+#include <stdlib.h>
+#include <dlfcn.h>
#include "effect_api.h"
#include "bass_boost.h"
@@ -41,6 +44,243 @@
"The Android Open Source Project",
};
+#define LIB_ACDB_LOADER "libacdbloader.so"
+#define PBE_CONF_APP_ID 0x00011134
+
+enum {
+ AUDIO_DEVICE_CAL_TYPE = 0,
+ AUDIO_STREAM_CAL_TYPE,
+};
+
+typedef struct acdb_audio_cal_cfg {
+ uint32_t persist;
+ uint32_t snd_dev_id;
+ uint32_t dev_id;
+ int32_t acdb_dev_id;
+ uint32_t app_type;
+ uint32_t topo_id;
+ uint32_t sampling_rate;
+ uint32_t cal_type;
+ uint32_t module_id;
+ uint32_t param_id;
+} acdb_audio_cal_cfg_t;
+
+typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
+static int pbe_load_config(struct pbe_params *params);
+
+/*
+ * Bass operations
+ */
+int bass_get_parameter(effect_context_t *context, effect_param_t *p,
+ uint32_t *size)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+ int32_t *param_tmp = (int32_t *)p->data;
+ int32_t param = *param_tmp++;
+ void *value = p->data + voffset;
+ int i;
+
+ ALOGV("%s", __func__);
+
+ p->status = 0;
+
+ switch (param) {
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+ if (p->vsize < sizeof(uint32_t))
+ p->status = -EINVAL;
+ p->vsize = sizeof(uint32_t);
+ break;
+ case BASSBOOST_PARAM_STRENGTH:
+ if (p->vsize < sizeof(int16_t))
+ p->status = -EINVAL;
+ p->vsize = sizeof(int16_t);
+ break;
+ default:
+ p->status = -EINVAL;
+ }
+
+ *size = sizeof(effect_param_t) + voffset + p->vsize;
+
+ if (p->status != 0)
+ return 0;
+
+ switch (param) {
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+ ALOGV("%s: BASSBOOST_PARAM_STRENGTH_SUPPORTED", __func__);
+ if (bass_ctxt->active_index == BASS_BOOST)
+ *(uint32_t *)value = 1;
+ else
+ *(uint32_t *)value = 0;
+ break;
+
+ case BASSBOOST_PARAM_STRENGTH:
+ ALOGV("%s: BASSBOOST_PARAM_STRENGTH", __func__);
+ if (bass_ctxt->active_index == BASS_BOOST)
+ *(int16_t *)value = bassboost_get_strength(&(bass_ctxt->bassboost_ctxt));
+ else
+ *(int16_t *)value = 0;
+ break;
+
+ default:
+ p->status = -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+int bass_set_parameter(effect_context_t *context, effect_param_t *p,
+ uint32_t size __unused)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+ void *value = p->data + voffset;
+ int32_t *param_tmp = (int32_t *)p->data;
+ int32_t param = *param_tmp++;
+ uint32_t strength;
+
+ ALOGV("%s", __func__);
+
+ p->status = 0;
+
+ switch (param) {
+ case BASSBOOST_PARAM_STRENGTH:
+ ALOGV("%s BASSBOOST_PARAM_STRENGTH", __func__);
+ if (bass_ctxt->active_index == BASS_BOOST) {
+ strength = (uint32_t)(*(int16_t *)value);
+ bassboost_set_strength(&(bass_ctxt->bassboost_ctxt), strength);
+ } else {
+ /* stength supported only for BB and not for PBE, but do not
+ * return error for unsupported case, as it fails cts test
+ */
+ ALOGD("%s ignore set strength, index %d",
+ __func__, bass_ctxt->active_index);
+ break;
+ }
+ break;
+ default:
+ p->status = -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+int bass_set_device(effect_context_t *context, uint32_t device)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ if (device == AUDIO_DEVICE_OUT_SPEAKER) {
+ bass_ctxt->active_index = BASS_PBE;
+ ALOGV("%s: set PBE mode, device: %x", __func__, device);
+ } else if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
+ device == AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+ device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) {
+ ALOGV("%s: set BB mode, device: %x", __func__, device);
+ bass_ctxt->active_index = BASS_BOOST;
+ } else {
+ ALOGI("%s: disabled by device: %x", __func__, device);
+ bass_ctxt->active_index = BASS_INVALID;
+ }
+
+ bassboost_set_device((effect_context_t *)&(bass_ctxt->bassboost_ctxt), device);
+ pbe_set_device((effect_context_t *)&(bass_ctxt->pbe_ctxt), device);
+
+ return 0;
+}
+
+int bass_reset(effect_context_t *context)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ bassboost_reset((effect_context_t *)&(bass_ctxt->bassboost_ctxt));
+ pbe_reset((effect_context_t *)&(bass_ctxt->pbe_ctxt));
+
+ return 0;
+}
+
+int bass_init(effect_context_t *context)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ // convery i/o channel config to sub effects
+ bass_ctxt->bassboost_ctxt.common.config = context->config;
+ bass_ctxt->pbe_ctxt.common.config = context->config;
+
+ ALOGV("%s", __func__);
+
+ bass_ctxt->active_index = BASS_BOOST;
+
+
+ bassboost_init((effect_context_t *)&(bass_ctxt->bassboost_ctxt));
+ pbe_init((effect_context_t *)&(bass_ctxt->pbe_ctxt));
+
+ return 0;
+}
+
+int bass_enable(effect_context_t *context)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ ALOGV("%s", __func__);
+
+ bassboost_enable((effect_context_t *)&(bass_ctxt->bassboost_ctxt));
+ pbe_enable((effect_context_t *)&(bass_ctxt->pbe_ctxt));
+
+ return 0;
+}
+
+int bass_disable(effect_context_t *context)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ ALOGV("%s", __func__);
+
+ bassboost_disable((effect_context_t *)&(bass_ctxt->bassboost_ctxt));
+ pbe_disable((effect_context_t *)&(bass_ctxt->pbe_ctxt));
+
+ return 0;
+}
+
+int bass_start(effect_context_t *context, output_context_t *output)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ ALOGV("%s", __func__);
+
+ bassboost_start((effect_context_t *)&(bass_ctxt->bassboost_ctxt), output);
+ pbe_start((effect_context_t *)&(bass_ctxt->pbe_ctxt), output);
+
+ return 0;
+}
+
+int bass_stop(effect_context_t *context, output_context_t *output)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ ALOGV("%s", __func__);
+
+ bassboost_stop((effect_context_t *)&(bass_ctxt->bassboost_ctxt), output);
+ pbe_stop((effect_context_t *)&(bass_ctxt->pbe_ctxt), output);
+
+ return 0;
+}
+
+int bass_set_mode(effect_context_t *context, int32_t hw_acc_fd)
+{
+ bass_context_t *bass_ctxt = (bass_context_t *)context;
+
+ ALOGV("%s", __func__);
+
+ bassboost_set_mode((effect_context_t *)&(bass_ctxt->bassboost_ctxt), hw_acc_fd);
+ pbe_set_mode((effect_context_t *)&(bass_ctxt->pbe_ctxt), hw_acc_fd);
+
+ return 0;
+}
+
+#undef LOG_TAG
+#define LOG_TAG "offload_effect_bb"
/*
* Bassboost operations
*/
@@ -70,99 +310,30 @@
return 0;
}
-int bassboost_get_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t *size)
-{
- bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
- int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
- int32_t *param_tmp = (int32_t *)p->data;
- int32_t param = *param_tmp++;
- void *value = p->data + voffset;
- int i;
-
- ALOGV("%s: ctxt %p, param %d", __func__, bass_ctxt, param);
-
- p->status = 0;
-
- switch (param) {
- case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
- if (p->vsize < sizeof(uint32_t))
- p->status = -EINVAL;
- p->vsize = sizeof(uint32_t);
- break;
- case BASSBOOST_PARAM_STRENGTH:
- if (p->vsize < sizeof(int16_t))
- p->status = -EINVAL;
- p->vsize = sizeof(int16_t);
- break;
- default:
- p->status = -EINVAL;
- }
-
- *size = sizeof(effect_param_t) + voffset + p->vsize;
-
- if (p->status != 0)
- return 0;
-
- switch (param) {
- case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
- *(uint32_t *)value = 1;
- break;
-
- case BASSBOOST_PARAM_STRENGTH:
- *(int16_t *)value = bassboost_get_strength(bass_ctxt);
- break;
-
- default:
- p->status = -EINVAL;
- break;
- }
-
- return 0;
-}
-
-int bassboost_set_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t size __unused)
-{
- bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
- int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
- void *value = p->data + voffset;
- int32_t *param_tmp = (int32_t *)p->data;
- int32_t param = *param_tmp++;
- uint32_t strength;
-
- ALOGV("%s: ctxt %p, param %d", __func__, bass_ctxt, param);
-
- p->status = 0;
-
- switch (param) {
- case BASSBOOST_PARAM_STRENGTH:
- strength = (uint32_t)(*(int16_t *)value);
- bassboost_set_strength(bass_ctxt, strength);
- break;
- default:
- p->status = -EINVAL;
- break;
- }
-
- return 0;
-}
-
int bassboost_set_device(effect_context_t *context, uint32_t device)
{
bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
ALOGV("%s: ctxt %p, device 0x%x", __func__, bass_ctxt, device);
bass_ctxt->device = device;
- if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
- (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
- (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) ||
-#ifdef AFE_PROXY_ENABLED
- (device == AUDIO_DEVICE_OUT_PROXY) ||
-#endif
- (device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
- (device == AUDIO_DEVICE_OUT_USB_ACCESSORY) ||
- (device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
+ if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
+ device == AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+ device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) {
+ if (bass_ctxt->temp_disabled) {
+ if (effect_is_active(&bass_ctxt->common)) {
+ offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
+ if (bass_ctxt->ctl)
+ offload_bassboost_send_params(bass_ctxt->ctl,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ if (bass_ctxt->hw_acc_fd > 0)
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ }
+ bass_ctxt->temp_disabled = false;
+ }
+ } else {
if (!bass_ctxt->temp_disabled) {
if (effect_is_active(&bass_ctxt->common)) {
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
@@ -178,21 +349,6 @@
bass_ctxt->temp_disabled = true;
}
ALOGI("%s: ctxt %p, disabled based on device", __func__, bass_ctxt);
- } else {
- if (bass_ctxt->temp_disabled) {
- if (effect_is_active(&bass_ctxt->common)) {
- offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
- if (bass_ctxt->ctl)
- offload_bassboost_send_params(bass_ctxt->ctl,
- &bass_ctxt->offload_bass,
- OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
- if (bass_ctxt->hw_acc_fd > 0)
- hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
- &bass_ctxt->offload_bass,
- OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
- }
- bass_ctxt->temp_disabled = false;
- }
}
offload_bassboost_set_device(&(bass_ctxt->offload_bass), device);
return 0;
@@ -329,3 +485,234 @@
OFFLOAD_SEND_BASSBOOST_STRENGTH);
return 0;
}
+
+#undef LOG_TAG
+#define LOG_TAG "offload_effect_pbe"
+/*
+ * PBE operations
+ */
+
+int pbe_set_device(effect_context_t *context, uint32_t device)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+ char propValue[PROPERTY_VALUE_MAX];
+ bool pbe_enabled_by_prop = false;
+
+ ALOGV("%s: device: %d", __func__, device);
+ pbe_ctxt->device = device;
+
+ if (property_get("audio.safx.pbe.enabled", propValue, NULL)) {
+ pbe_enabled_by_prop = atoi(propValue) ||
+ !strncmp("true", propValue, 4);
+ }
+
+ if (device == AUDIO_DEVICE_OUT_SPEAKER && pbe_enabled_by_prop == true) {
+ if (pbe_ctxt->temp_disabled) {
+ if (effect_is_active(&pbe_ctxt->common)) {
+ offload_pbe_set_enable_flag(&(pbe_ctxt->offload_pbe), true);
+ if (pbe_ctxt->ctl)
+ offload_pbe_send_params(pbe_ctxt->ctl,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ if (pbe_ctxt->hw_acc_fd > 0)
+ hw_acc_pbe_send_params(pbe_ctxt->hw_acc_fd,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ }
+ pbe_ctxt->temp_disabled = false;
+ }
+ } else {
+ if (!pbe_ctxt->temp_disabled) {
+ if (effect_is_active(&pbe_ctxt->common)) {
+ offload_pbe_set_enable_flag(&(pbe_ctxt->offload_pbe), false);
+ if (pbe_ctxt->ctl)
+ offload_pbe_send_params(pbe_ctxt->ctl,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG);
+ if (pbe_ctxt->hw_acc_fd > 0)
+ hw_acc_pbe_send_params(pbe_ctxt->hw_acc_fd,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG);
+ }
+ pbe_ctxt->temp_disabled = true;
+ }
+ }
+ offload_pbe_set_device(&(pbe_ctxt->offload_pbe), device);
+ return 0;
+}
+
+int pbe_reset(effect_context_t *context)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ return 0;
+}
+
+int pbe_init(effect_context_t *context)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ ALOGV("%s", __func__);
+ context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ context->config.inputCfg.samplingRate = 44100;
+ context->config.inputCfg.bufferProvider.getBuffer = NULL;
+ context->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ context->config.inputCfg.bufferProvider.cookie = NULL;
+ context->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+ context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ context->config.outputCfg.samplingRate = 44100;
+ context->config.outputCfg.bufferProvider.getBuffer = NULL;
+ context->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ context->config.outputCfg.bufferProvider.cookie = NULL;
+ context->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ set_config(context, &context->config);
+
+ pbe_ctxt->hw_acc_fd = -1;
+ pbe_ctxt->temp_disabled = false;
+ memset(&(pbe_ctxt->offload_pbe), 0, sizeof(struct pbe_params));
+ pbe_load_config(&(pbe_ctxt->offload_pbe));
+
+ return 0;
+}
+
+int pbe_enable(effect_context_t *context)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ ALOGV("%s", __func__);
+
+ if (!offload_pbe_get_enable_flag(&(pbe_ctxt->offload_pbe)) &&
+ !(pbe_ctxt->temp_disabled)) {
+ offload_pbe_set_enable_flag(&(pbe_ctxt->offload_pbe), true);
+ if (pbe_ctxt->ctl)
+ offload_pbe_send_params(pbe_ctxt->ctl,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ if (pbe_ctxt->hw_acc_fd > 0)
+ hw_acc_pbe_send_params(pbe_ctxt->hw_acc_fd,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ }
+ return 0;
+}
+
+int pbe_disable(effect_context_t *context)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ ALOGV("%s", __func__);
+ if (offload_pbe_get_enable_flag(&(pbe_ctxt->offload_pbe))) {
+ offload_pbe_set_enable_flag(&(pbe_ctxt->offload_pbe), false);
+ if (pbe_ctxt->ctl)
+ offload_pbe_send_params(pbe_ctxt->ctl,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG);
+ if (pbe_ctxt->hw_acc_fd > 0)
+ hw_acc_pbe_send_params(pbe_ctxt->hw_acc_fd,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG);
+ }
+ return 0;
+}
+
+int pbe_start(effect_context_t *context, output_context_t *output)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ ALOGV("%s", __func__);
+ pbe_ctxt->ctl = output->ctl;
+ ALOGV("output->ctl: %p", output->ctl);
+ if (offload_pbe_get_enable_flag(&(pbe_ctxt->offload_pbe))) {
+ if (pbe_ctxt->ctl)
+ offload_pbe_send_params(pbe_ctxt->ctl, &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ if (pbe_ctxt->hw_acc_fd > 0)
+ hw_acc_pbe_send_params(pbe_ctxt->hw_acc_fd,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ }
+ return 0;
+}
+
+int pbe_stop(effect_context_t *context, output_context_t *output __unused)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ ALOGV("%s", __func__);
+ pbe_ctxt->ctl = NULL;
+ return 0;
+}
+
+int pbe_set_mode(effect_context_t *context, int32_t hw_acc_fd)
+{
+ pbe_context_t *pbe_ctxt = (pbe_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, pbe_ctxt);
+ pbe_ctxt->hw_acc_fd = hw_acc_fd;
+ if ((pbe_ctxt->hw_acc_fd > 0) &&
+ (offload_pbe_get_enable_flag(&(pbe_ctxt->offload_pbe))))
+ hw_acc_pbe_send_params(pbe_ctxt->hw_acc_fd,
+ &pbe_ctxt->offload_pbe,
+ OFFLOAD_SEND_PBE_ENABLE_FLAG |
+ OFFLOAD_SEND_PBE_CONFIG);
+ return 0;
+}
+
+static int pbe_load_config(struct pbe_params *params)
+{
+ int ret = 0;
+ uint32_t len = 0;
+ uint32_t propValue = 0;
+ uint32_t pbe_app_type = PBE_CONF_APP_ID;
+ char propValueStr[PROPERTY_VALUE_MAX];
+ void *acdb_handle = NULL;
+ acdb_get_audio_cal_t acdb_get_audio_cal = NULL;
+ acdb_audio_cal_cfg_t cal_cfg = {0};
+
+ acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
+ if (acdb_handle == NULL) {
+ ALOGE("%s error opening library %s", __func__, LIB_ACDB_LOADER);
+ return -EFAULT;
+ }
+
+ acdb_get_audio_cal = (acdb_get_audio_cal_t)dlsym(acdb_handle,
+ "acdb_loader_get_audio_cal_v2");
+ if (acdb_get_audio_cal == NULL) {
+ dlclose(acdb_handle);
+ ALOGE("%s error resolving acdb func symbols", __func__);
+ return -EFAULT;
+ }
+ if (property_get("audio.safx.pbe.app.type", propValueStr, "0")) {
+ propValue = atoll(propValueStr);
+ if (propValue != 0) {
+ pbe_app_type = propValue;
+ }
+ }
+ ALOGD("%s pbe_app_type = 0x%.8x", __func__, pbe_app_type);
+
+ cal_cfg.persist = 1;
+ cal_cfg.cal_type = AUDIO_STREAM_CAL_TYPE;
+ cal_cfg.app_type = pbe_app_type;
+ cal_cfg.module_id = PBE_CONF_MODULE_ID;
+ cal_cfg.param_id = PBE_CONF_PARAM_ID;
+
+ len = sizeof(params->config);
+ ret = acdb_get_audio_cal((void *)&cal_cfg, (void*)&(params->config), &len);
+ ALOGD("%s ret = %d, len = %u", __func__, ret, len);
+ if (ret == 0)
+ params->cfg_len = len;
+
+ dlclose(acdb_handle);
+ return ret;
+}
diff --git a/post_proc/bass_boost.h b/post_proc/bass_boost.h
index 6f0e61b..14d6c97 100644
--- a/post_proc/bass_boost.h
+++ b/post_proc/bass_boost.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -22,6 +22,13 @@
#include "bundle.h"
+enum {
+ BASS_INVALID = -1,
+ BASS_BOOST = 0, // index of bassboost
+ BASS_PBE, // index of PBE
+ BASS_COUNT // totol number of bass type
+};
+
extern const effect_descriptor_t bassboost_descriptor;
typedef struct bassboost_context_s {
@@ -37,11 +44,50 @@
struct bass_boost_params offload_bass;
} bassboost_context_t;
-int bassboost_get_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t *size);
+typedef struct pbe_context_s {
+ effect_context_t common;
-int bassboost_set_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t size);
+ // Offload vars
+ struct mixer_ctl *ctl;
+ int hw_acc_fd;
+ bool temp_disabled;
+ uint32_t device;
+ struct pbe_params offload_pbe;
+} pbe_context_t;
+
+typedef struct bass_context_s {
+ effect_context_t common;
+ bassboost_context_t bassboost_ctxt;
+ pbe_context_t pbe_ctxt;
+ int active_index;
+} bass_context_t;
+
+int bass_get_parameter(effect_context_t *context, effect_param_t *p,
+ uint32_t *size);
+
+int bass_set_parameter(effect_context_t *context, effect_param_t *p,
+ uint32_t size);
+
+int bass_set_device(effect_context_t *context, uint32_t device);
+
+int bass_set_mode(effect_context_t *context, int32_t hw_acc_fd);
+
+int bass_reset(effect_context_t *context);
+
+int bass_init(effect_context_t *context);
+
+int bass_enable(effect_context_t *context);
+
+int bass_disable(effect_context_t *context);
+
+int bass_start(effect_context_t *context, output_context_t *output);
+
+int bass_stop(effect_context_t *context, output_context_t *output);
+
+
+int bassboost_get_strength(bassboost_context_t *context);
+
+int bassboost_set_strength(bassboost_context_t *context, uint32_t strength);
int bassboost_set_device(effect_context_t *context, uint32_t device);
@@ -59,4 +105,20 @@
int bassboost_stop(effect_context_t *context, output_context_t *output);
+int pbe_set_device(effect_context_t *context, uint32_t device);
+
+int pbe_set_mode(effect_context_t *context, int32_t hw_acc_fd);
+
+int pbe_reset(effect_context_t *context);
+
+int pbe_init(effect_context_t *context);
+
+int pbe_enable(effect_context_t *context);
+
+int pbe_disable(effect_context_t *context);
+
+int pbe_start(effect_context_t *context, output_context_t *output);
+
+int pbe_stop(effect_context_t *context, output_context_t *output);
+
#endif /* OFFLOAD_EFFECT_BASS_BOOST_H_ */
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 606c66b..e38a41c 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -520,25 +520,26 @@
eq_ctxt->ctl = NULL;
} else if (memcmp(uuid, &bassboost_descriptor.uuid,
sizeof(effect_uuid_t)) == 0) {
- bassboost_context_t *bass_ctxt = (bassboost_context_t *)
- calloc(1, sizeof(bassboost_context_t));
+ bass_context_t *bass_ctxt = (bass_context_t *)
+ calloc(1, sizeof(bass_context_t));
if (bass_ctxt == NULL) {
return -ENOMEM;
}
context = (effect_context_t *)bass_ctxt;
- context->ops.init = bassboost_init;
- context->ops.reset = bassboost_reset;
- context->ops.set_parameter = bassboost_set_parameter;
- context->ops.get_parameter = bassboost_get_parameter;
- context->ops.set_device = bassboost_set_device;
- context->ops.set_hw_acc_mode = bassboost_set_mode;
- context->ops.enable = bassboost_enable;
- context->ops.disable = bassboost_disable;
- context->ops.start = bassboost_start;
- context->ops.stop = bassboost_stop;
+ context->ops.init = bass_init;
+ context->ops.reset = bass_reset;
+ context->ops.set_parameter = bass_set_parameter;
+ context->ops.get_parameter = bass_get_parameter;
+ context->ops.set_device = bass_set_device;
+ context->ops.set_hw_acc_mode = bass_set_mode;
+ context->ops.enable = bass_enable;
+ context->ops.disable = bass_disable;
+ context->ops.start = bass_start;
+ context->ops.stop = bass_stop;
context->desc = &bassboost_descriptor;
- bass_ctxt->ctl = NULL;
+ bass_ctxt->bassboost_ctxt.ctl = NULL;
+ bass_ctxt->pbe_ctxt.ctl = NULL;
} else if (memcmp(uuid, &virtualizer_descriptor.uuid,
sizeof(effect_uuid_t)) == 0) {
virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)
@@ -847,8 +848,6 @@
} break;
case EFFECT_CMD_SET_PARAM: {
if (pCmdData == NULL ||
- cmdSize > (int)(sizeof(effect_param_t) + sizeof(uint32_t) +
- sizeof(uint32_t)) ||
cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) +
sizeof(uint16_t)) ||
pReplyData == NULL || *replySize != sizeof(int32_t)) {
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index 7c1968e..e15db17 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -114,7 +114,7 @@
return -EINVAL;
} else {
*ctl = mixer_get_ctl_by_name(*mixer, mixer_string);
- if (!ctl) {
+ if (!(*ctl)) {
ALOGE("mixer_get_ctl_by_name failed");
mixer_close(*mixer);
*mixer = NULL;
@@ -235,6 +235,83 @@
bassboost, param_send_flags);
}
+void offload_pbe_set_device(struct pbe_params *pbe,
+ uint32_t device)
+{
+ ALOGV("%s: device=%d", __func__, device);
+ pbe->device = device;
+}
+
+void offload_pbe_set_enable_flag(struct pbe_params *pbe,
+ bool enable)
+{
+ ALOGV("%s: enable=%d", __func__, enable);
+ pbe->enable_flag = enable;
+}
+
+int offload_pbe_get_enable_flag(struct pbe_params *pbe)
+{
+ ALOGV("%s: enabled=%d", __func__, pbe->enable_flag);
+ return pbe->enable_flag;
+}
+
+static int pbe_send_params(eff_mode_t mode, void *ctl,
+ struct pbe_params *pbe,
+ unsigned param_send_flags)
+{
+ int param_values[128] = {0};
+ int i, *p_param_values = param_values, *cfg = NULL;
+
+ ALOGV("%s: enabled=%d", __func__, pbe->enable_flag);
+ *p_param_values++ = PBE_MODULE;
+ *p_param_values++ = pbe->device;
+ *p_param_values++ = 0; /* num of commands*/
+ if (param_send_flags & OFFLOAD_SEND_PBE_ENABLE_FLAG) {
+ *p_param_values++ = PBE_ENABLE;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = PBE_ENABLE_PARAM_LEN;
+ *p_param_values++ = pbe->enable_flag;
+ param_values[2] += 1;
+ }
+ if (param_send_flags & OFFLOAD_SEND_PBE_CONFIG) {
+ *p_param_values++ = PBE_CONFIG;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = pbe->cfg_len;
+ cfg = (int *)&pbe->config;
+ for (i = 0; i < (int)pbe->cfg_len ; i+= sizeof(*p_param_values))
+ *p_param_values++ = *cfg++;
+ param_values[2] += 1;
+ }
+
+ if ((mode == OFFLOAD) && param_values[2] && ctl) {
+ mixer_ctl_set_array((struct mixer_ctl *)ctl, param_values,
+ ARRAY_SIZE(param_values));
+ } else if ((mode == HW_ACCELERATOR) && param_values[2] &&
+ ctl && *(int *)ctl) {
+ if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+ ALOGE("%s: sending h/w acc effects params fail[%d]", __func__, errno);
+ }
+
+ return 0;
+}
+
+int offload_pbe_send_params(struct mixer_ctl *ctl,
+ struct pbe_params *pbe,
+ unsigned param_send_flags)
+{
+ return pbe_send_params(OFFLOAD, (void *)ctl, pbe,
+ param_send_flags);
+}
+
+int hw_acc_pbe_send_params(int fd, struct pbe_params *pbe,
+ unsigned param_send_flags)
+{
+ return pbe_send_params(HW_ACCELERATOR, (void *)&fd,
+ pbe, param_send_flags);
+}
+
void offload_virtualizer_set_device(struct virtualizer_params *virtualizer,
uint32_t device)
{
@@ -891,6 +968,11 @@
uint32_t i;
ALOGV("%s", __func__);
+ if (!ctl) {
+ ALOGE("%s: ctl is NULL, return invalid", __func__);
+ return -EINVAL;
+ }
+
if (param_send_flags & OFFLOAD_SEND_HPX_STATE_OFF) {
*p_param_values++ = DTS_EAGLE_MODULE_ENABLE;
*p_param_values++ = 0; /* hpx off*/
@@ -899,7 +981,7 @@
*p_param_values++ = 1; /* hpx on*/
}
- if ((mode == OFFLOAD) && ctl)
+ if (mode == OFFLOAD)
mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
else {
if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
diff --git a/post_proc/effect_api.h b/post_proc/effect_api.h
index e05924a..ce0503a 100644
--- a/post_proc/effect_api.h
+++ b/post_proc/effect_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -39,6 +39,21 @@
struct mixer_ctl **ctl);
void offload_close_mixer(struct mixer **mixer);
+
+#define OFFLOAD_SEND_PBE_ENABLE_FLAG (1 << 0)
+#define OFFLOAD_SEND_PBE_CONFIG (OFFLOAD_SEND_PBE_ENABLE_FLAG << 1)
+void offload_pbe_set_device(struct pbe_params *pbe,
+ uint32_t device);
+void offload_pbe_set_enable_flag(struct pbe_params *pbe,
+ bool enable);
+int offload_pbe_get_enable_flag(struct pbe_params *pbe);
+
+int offload_pbe_send_params(struct mixer_ctl *ctl,
+ struct pbe_params *pbe,
+ unsigned param_send_flags);
+int hw_acc_pbe_send_params(int fd,
+ struct pbe_params *pbe,
+ unsigned param_send_flags);
#define OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG (1 << 0)
#define OFFLOAD_SEND_BASSBOOST_STRENGTH \
(OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG << 1)