hal: Support config selection for playback on speaker
Support bit width selection for playback on speakers based on
platform info.
Change-Id: I8dd2cc7049186e7468615a43db550d7d580a81d1
hal: add support for source tracking feature
Change-Id: I019b22d6541e6d1a10552d808c3320a998b86e48
hal: Add source tracking support for bear family PLs
Change-Id: Ib455933c14fd4cb920ab5e19d879a48ef61686a3
hal: Add provision to select backend based on codec type
Change-Id: I9c0dd7d952ab9d6b9bf738074d97597622e09590
Change-Id: I9c0dd7d952ab9d6b9bf738074d97597622e09590
diff --git a/msm8909/hal/Android.mk b/msm8909/hal/Android.mk
index 18d1f32..1aeedaf 100644
--- a/msm8909/hal/Android.mk
+++ b/msm8909/hal/Android.mk
@@ -195,6 +195,11 @@
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/msm8909/hal/audio_extn/audio_extn.c b/msm8909/hal/audio_extn/audio_extn.c
index 043177c..3b13d9a 100644
--- a/msm8909/hal/audio_extn/audio_extn.c
+++ b/msm8909/hal/audio_extn/audio_extn.c
@@ -71,6 +71,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
@@ -468,6 +479,7 @@
audio_extn_ds2_set_parameters(adev, parms);
audio_extn_customstereo_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,
@@ -478,7 +490,7 @@
audio_extn_get_afe_proxy_parameters(query, reply);
audio_extn_get_fluence_parameters(adev, query, reply);
get_active_offload_usecases(adev, 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);
free(kv_pairs);
diff --git a/msm8909/hal/audio_extn/source_track.c b/msm8909/hal/audio_extn/source_track.c
new file mode 100644
index 0000000..316e52d
--- /dev/null
+++ b/msm8909/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/msm8909/hal/audio_extn/utils.c b/msm8909/hal/audio_extn/utils.c
index 0429a45..4c20c84 100644
--- a/msm8909/hal/audio_extn/utils.c
+++ b/msm8909/hal/audio_extn/utils.c
@@ -441,6 +441,9 @@
if ((24 == bit_width) &&
(devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+ int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
+ if (-ENOSYS != bw)
+ bit_width = (uint32_t)bw;
sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
}
diff --git a/msm8909/hal/audio_hw.c b/msm8909/hal/audio_hw.c
index 1c177fc..7417c39 100644
--- a/msm8909/hal/audio_hw.c
+++ b/msm8909/hal/audio_hw.c
@@ -727,14 +727,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;
}
@@ -791,7 +792,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;
diff --git a/msm8909/hal/audio_hw.h b/msm8909/hal/audio_hw.h
index d05f743..d86bdb9 100644
--- a/msm8909/hal/audio_hw.h
+++ b/msm8909/hal/audio_hw.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
@@ -320,6 +320,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/msm8909/hal/msm8916/platform.c b/msm8909/hal/msm8916/platform.c
index ea75a4a..eb05a27 100644
--- a/msm8909/hal/msm8916/platform.c
+++ b/msm8909/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
@@ -589,7 +589,6 @@
return ret;
}
-
static void update_codec_type(const char *snd_card_name) {
if (!strncmp(snd_card_name, "msm8939-tapan-snd-card",
@@ -598,13 +597,13 @@
sizeof("msm8939-tapan9302-snd-card"))||
!strncmp(snd_card_name, "msm8939-tomtom9330-snd-card",
sizeof("msm8939-tomtom9330-snd-card")) ||
- !strncmp(snd_card_name, "msm8x09-tasha9326-snd-card",
- sizeof("msm8x09-tasha9326-snd-card")))
- {
+ !strncmp(snd_card_name, "msm8x09-tasha9326-snd-card",
+ sizeof("msm8x09-tasha9326-snd-card"))) {
ALOGI("%s: snd_card_name: %s",__func__,snd_card_name);
is_external_codec = true;
}
}
+
static void query_platform(const char *snd_card_name,
char *mixer_xml_path)
{
@@ -1554,6 +1553,18 @@
return acdb_device_table[snd_device];
}
+int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width)
+{
+ ALOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
+
+int platform_get_snd_device_bit_width(snd_device_t snd_device)
+{
+ ALOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
+
int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
int app_type, int sample_rate)
{
@@ -2962,3 +2973,68 @@
strlcpy(buf, PLATFORM_IMAGE_NAME, sizeof(PLATFORM_IMAGE_NAME));
return 0;
}
+
+/*
+ * 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.
+ * The audio interface for a particular input device need to be added 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), ""},
+ {AUDIO_DEVICE_IN_BACK_MIC, ENUM_TO_STRING(AUDIO_DEVICE_IN_BACK_MIC), ""},
+};
+
+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,
+ const char *codec_type)
+{
+ int ret = 0;
+ int i;
+
+ if (device_name == NULL || intf_name == NULL || codec_type == NULL) {
+ ALOGE("%s: Invalid input", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGD("%s: Enter, device name:%s, intf name:%s, codec_type:%s", __func__,
+ device_name, intf_name, codec_type);
+
+ 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)) {
+ if (is_external_codec &&
+ (strncmp(codec_type, "external", strlen(codec_type)) == 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));
+ } else if (!is_external_codec &&
+ (strncmp(codec_type, "internal", strlen(codec_type)) == 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));
+ } else
+ ALOGE("Invalid codec_type specified. Ignoring this interface entry.");
+ goto done;
+ }
+ }
+ ALOGE("%s: Could not find matching device name %s",
+ __func__, device_name);
+
+ ret = -EINVAL;
+
+done:
+ return ret;
+}
diff --git a/msm8909/hal/msm8916/platform.h b/msm8909/hal/msm8916/platform.h
index 80852b5..15c6473 100644
--- a/msm8909/hal/msm8916/platform.h
+++ b/msm8909/hal/msm8916/platform.h
@@ -264,4 +264,12 @@
int platform_get_subsys_image_name (char *buf);
+
+#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/msm8909/hal/msm8960/platform.c b/msm8909/hal/msm8960/platform.c
index 593b66a..dcb85aa 100644
--- a/msm8909/hal/msm8960/platform.c
+++ b/msm8909/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
@@ -421,6 +421,18 @@
return -ENOSYS;
}
+int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width)
+{
+ ALOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
+
+int platform_get_snd_device_bit_width(snd_device_t snd_device)
+{
+ ALOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
+
int platform_switch_voice_call_enable_device_config(void *platform __unused,
snd_device_t out_snd_device __unused,
snd_device_t in_snd_device __unused)
@@ -1086,3 +1098,10 @@
{
return 0;
}
+
+int platform_set_audio_device_interface(const char * device_name __unused,
+ const char *intf_name __unused,
+ const char *codec_type __unused)
+{
+ return -ENOSYS;
+}
diff --git a/msm8909/hal/msm8974/platform.c b/msm8909/hal/msm8974/platform.c
index 59a4af1..ed57cd9 100644
--- a/msm8909/hal/msm8974/platform.c
+++ b/msm8909/hal/msm8974/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
@@ -334,6 +334,9 @@
[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = "speaker-dmic-broadside",
};
+// Platform specific backend bit width table
+static int backend_bit_width_table[SND_DEVICE_MAX] = {0};
+
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
static int acdb_device_table[SND_DEVICE_MAX] = {
[SND_DEVICE_NONE] = -1,
@@ -796,6 +799,9 @@
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
backend_table[dev] = NULL;
}
+ for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
+ backend_bit_width_table[dev] = 16;
+ }
// TBD - do these go to the platform-info.xml file.
// will help in avoiding strdups here
@@ -1397,7 +1403,32 @@
return acdb_device_table[snd_device];
}
-int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
+int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width)
+{
+ int ret = 0;
+
+ if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d",
+ __func__, snd_device);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ backend_bit_width_table[snd_device] = bit_width;
+done:
+ return ret;
+}
+
+int platform_get_snd_device_bit_width(snd_device_t snd_device)
+{
+ if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+ return DEFAULT_OUTPUT_SAMPLING_RATE;
+ }
+ return backend_bit_width_table[snd_device];
+}
+
+int platform_send_audio_calibration(void *platform, snd_device_t snd_device,
int app_type, int sample_rate)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -2834,11 +2865,15 @@
}
}
- // 24 bit playback on speakers and all 16 bit playbacks is allowed through
- // 16 bit/48 khz backend only
- if ((16 == bit_width) ||
- ((24 == bit_width) &&
- (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER))) {
+ // 16 bit playback on speakers is allowed through 48 khz backend only
+ if (16 == bit_width) {
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+ // 24 bit playback on speakers is allowed through 48 khz backend only
+ // bit width re-configured based on platform info
+ if ((24 == bit_width) &&
+ (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+ bit_width = (uint32_t)platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
}
// Force routing if the expected bitwdith or samplerate
@@ -2917,3 +2952,53 @@
*device_to_be_id = msm_device_to_be_id;
*length = msm_be_id_array_len;
}
+ /* 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,
+ const char *codec_type __unused)
+{
+ 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/msm8909/hal/msm8974/platform.h b/msm8909/hal/msm8974/platform.h
index 6358e9d..5bd1e2b 100644
--- a/msm8909/hal/msm8974/platform.h
+++ b/msm8909/hal/msm8974/platform.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
@@ -344,4 +344,18 @@
get_sample_rate_t get_sample_rate;
};
+/*
+ * ID for setting mute and lateny on the device side
+ * through Device PP Params mixer control.
+ */
+#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/msm8909/hal/platform_api.h b/msm8909/hal/platform_api.h
index 2222b6e..cdbf27b 100644
--- a/msm8909/hal/platform_api.h
+++ b/msm8909/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
@@ -38,6 +38,8 @@
int platform_get_fluence_type(void *platform, char *value, uint32_t len);
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_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width);
+int platform_get_snd_device_bit_width(snd_device_t snd_device);
int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
int app_type, int sample_rate);
int platform_get_default_app_type(void *platform);
@@ -96,4 +98,6 @@
void platform_set_echo_reference(void *platform, bool enable);
void platform_get_device_to_be_id_map(int **be_id_map, int *length);
+int platform_set_audio_device_interface(const char * device_name, const char *intf_name,
+ const char * codec_type);
#endif // AUDIO_PLATFORM_API_H
diff --git a/msm8909/hal/platform_info.c b/msm8909/hal/platform_info.c
index 615b9f3..b65411f 100644
--- a/msm8909/hal/platform_info.c
+++ b/msm8909/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
@@ -43,22 +43,28 @@
typedef enum {
ROOT,
ACDB,
+ BITWIDTH,
PCM_ID,
BACKEND_NAME,
+ INTERFACE_NAME,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
static void process_acdb_id(const XML_Char **attr);
+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[] = {
[ROOT] = process_root,
[ACDB] = process_acdb_id,
+ [BITWIDTH] = process_bit_width,
[PCM_ID] = process_pcm_id,
[BACKEND_NAME] = process_backend_name,
+ [INTERFACE_NAME] = process_interface_name,
};
static section_t section;
@@ -80,6 +86,11 @@
* ...
* ...
* </pcm_ids>
+ * <interface_names>
+ * <device name="Use audio device name here, not sound device name" interface="PRIMARY_I2S" codec_type="external/internal"/>
+ * ...
+ * ...
+ * </interface_names>
* </audio_platform_info>
*/
@@ -202,6 +213,74 @@
return;
}
+static void process_bit_width(const XML_Char **attr)
+{
+ int index;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found, no ACDB 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 ACDB ID set!",
+ __func__, attr[1]);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "bit_width") != 0) {
+ ALOGE("%s: Device %s in platform info xml has no bit_width, no ACDB ID set!",
+ __func__, attr[1]);
+ goto done;
+ }
+
+ if (platform_set_snd_device_bit_width(index, atoi((char *)attr[3])) < 0) {
+ ALOGE("%s: Device %s, ACDB ID %d was not set!",
+ __func__, attr[1], atoi((char *)attr[3]));
+ goto done;
+ }
+
+done:
+ 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;
+ }
+
+ if (strcmp(attr[4], "codec_type") != 0) {
+ ALOGE("%s: Device %s has no codec type set!",
+ __func__, attr[1]);
+
+ goto done;
+ }
+
+ ret = platform_set_audio_device_interface((char *)attr[1], (char *)attr[3],
+ (char *)attr[5]);
+ 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)
{
@@ -209,15 +288,20 @@
const XML_Char *attr_value = NULL;
unsigned int i;
- if (strcmp(tag_name, "acdb_ids") == 0) {
+ if (strcmp(tag_name, "bit_width_configs") == 0) {
+ section = BITWIDTH;
+ } else if (strcmp(tag_name, "acdb_ids") == 0) {
section = ACDB;
} else if (strcmp(tag_name, "pcm_ids") == 0) {
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)) {
- 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;
}
@@ -239,12 +323,16 @@
static void end_tag(void *userdata __unused, const XML_Char *tag_name)
{
- if (strcmp(tag_name, "acdb_ids") == 0) {
+ if (strcmp(tag_name, "bit_width_configs") == 0) {
+ section = ROOT;
+ } else if (strcmp(tag_name, "acdb_ids") == 0) {
section = ROOT;
} else if (strcmp(tag_name, "pcm_ids") == 0) {
section = ROOT;
} else if (strcmp(tag_name, "backend_names") == 0) {
section = ROOT;
+ } else if (strcmp(tag_name, "interface_names") == 0) {
+ section = ROOT;
}
}