hal: add support for tx app type config
Add support for capture path calibration
according to app type.
Change-Id: I7f5e54b3d567611420d3abba159fbbc24e6e25ca
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 07714f6..7c3f98d 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -501,14 +501,17 @@
void audio_extn_pm_unvote(void);
#endif
-void audio_extn_utils_update_streams_output_cfg_list(void *platform,
+void audio_extn_utils_update_streams_cfg_lists(void *platform,
struct mixer *mixer,
- struct listnode *streams_output_cfg_list);
-void audio_extn_utils_dump_streams_output_cfg_list(
- struct listnode *streams_output_cfg_list);
-void audio_extn_utils_release_streams_output_cfg_list(
- struct listnode *streams_output_cfg_list);
-void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list);
+void audio_extn_utils_dump_streams_cfg_lists(
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list);
+void audio_extn_utils_release_streams_cfg_lists(
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list);
+void audio_extn_utils_update_stream_output_app_type_cfg(void *platform,
struct listnode *streams_output_cfg_list,
audio_devices_t devices,
audio_output_flags_t flags,
@@ -517,10 +520,21 @@
uint32_t bit_width,
audio_channel_mask_t channel_mask,
struct stream_app_type_cfg *app_type_cfg);
+void audio_extn_utils_update_stream_input_app_type_cfg(void *platform,
+ struct listnode *streams_input_cfg_list,
+ audio_devices_t devices,
+ audio_input_flags_t flags,
+ audio_format_t format,
+ uint32_t sample_rate,
+ uint32_t bit_width,
+ struct stream_app_type_cfg *app_type_cfg);
int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
struct audio_usecase *usecase);
void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
struct audio_usecase *usecase);
+void audio_extn_utils_update_stream_app_type_cfg_for_usecase(
+ struct audio_device *adev,
+ struct audio_usecase *usecase);
#ifdef DS2_DOLBY_DAP_ENABLED
#define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
#define SET_HW_INFO_FUNC "dap_hal_set_hw_info"
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 90b39b5..45ea3b7 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -43,11 +43,14 @@
#ifdef LINUX_ENABLED
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/etc/audio_output_policy.conf"
+#define AUDIO_IO_POLICY_VENDOR_CONFIG_FILE "/etc/audio_io_policy.conf"
#else
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
+#define AUDIO_IO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_io_policy.conf"
#endif
#define OUTPUTS_TAG "outputs"
+#define INPUTS_TAG "inputs"
#define DYNAMIC_VALUE_TAG "dynamic"
#define FLAGS_TAG "flags"
@@ -95,6 +98,11 @@
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
#endif
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_NONE),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC),
};
const struct string_to_enum s_format_name_to_enum_table[] = {
@@ -161,9 +169,10 @@
return 0;
}
-static audio_output_flags_t parse_flag_names(char *name)
+static audio_io_flags_t parse_flag_names(char *name)
{
uint32_t flag = 0;
+ audio_io_flags_t io_flags;
char *last_r;
char *flag_name = strtok_r(name, "|", &last_r);
while (flag_name != NULL) {
@@ -176,10 +185,12 @@
}
ALOGV("parse_flag_names: flag - %d", flag);
- return (audio_output_flags_t)flag;
+ io_flags.in_flags = (audio_input_flags_t)flag;
+ io_flags.out_flags = (audio_output_flags_t)flag;
+ return io_flags;
}
-static void parse_format_names(char *name, struct streams_output_cfg *so_info)
+static void parse_format_names(char *name, struct streams_io_cfg *s_info)
{
struct stream_format *sf_info = NULL;
char *last_r;
@@ -188,7 +199,7 @@
if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
return;
- list_init(&so_info->format_list);
+ list_init(&s_info->format_list);
while (str != NULL) {
audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
ARRAY_SIZE(s_format_name_to_enum_table), str);
@@ -199,13 +210,13 @@
break; /* return whatever was parsed */
sf_info->format = format;
- list_add_tail(&so_info->format_list, &sf_info->list);
+ list_add_tail(&s_info->format_list, &sf_info->list);
}
str = strtok_r(NULL, "|", &last_r);
}
}
-static void parse_sample_rate_names(char *name, struct streams_output_cfg *so_info)
+static void parse_sample_rate_names(char *name, struct streams_io_cfg *s_info)
{
struct stream_sample_rate *ss_info = NULL;
uint32_t sample_rate = 48000;
@@ -215,7 +226,7 @@
if (str != NULL && 0 == strcmp(str, DYNAMIC_VALUE_TAG))
return;
- list_init(&so_info->sample_rate_list);
+ list_init(&s_info->sample_rate_list);
while (str != NULL) {
sample_rate = (uint32_t)strtol(str, (char **)NULL, 10);
ALOGV("%s: sample_rate - %d", __func__, sample_rate);
@@ -226,7 +237,7 @@
return;
}
ss_info->sample_rate = sample_rate;
- list_add_tail(&so_info->sample_rate_list, &ss_info->list);
+ list_add_tail(&s_info->sample_rate_list, &ss_info->list);
}
str = strtok_r(NULL, "|", &last_r);
}
@@ -258,65 +269,80 @@
return app_type;
}
-static void update_streams_output_cfg_list(cnode *root, void *platform,
- struct listnode *streams_output_cfg_list)
+static void update_streams_cfg_list(cnode *root, void *platform,
+ struct listnode *streams_cfg_list)
{
cnode *node = root->first_child;
- struct streams_output_cfg *so_info;
+ struct streams_io_cfg *s_info;
ALOGV("%s", __func__);
- so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
+ s_info = (struct streams_io_cfg *)calloc(1, sizeof(struct streams_io_cfg));
- if (!so_info) {
- ALOGE("failed to allocate mem for so_info list element");
+ if (!s_info) {
+ ALOGE("failed to allocate mem for s_info list element");
return;
}
while (node) {
if (strcmp(node->name, FLAGS_TAG) == 0) {
- so_info->flags = parse_flag_names((char *)node->value);
+ s_info->flags = parse_flag_names((char *)node->value);
} else if (strcmp(node->name, FORMATS_TAG) == 0) {
- parse_format_names((char *)node->value, so_info);
+ parse_format_names((char *)node->value, s_info);
} else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
- so_info->app_type_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- parse_sample_rate_names((char *)node->value, so_info);
+ s_info->app_type_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ parse_sample_rate_names((char *)node->value, s_info);
} else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
- so_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
+ s_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
} else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
- so_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
+ s_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
}
node = node->next;
}
- list_add_tail(streams_output_cfg_list, &so_info->list);
+ list_add_tail(streams_cfg_list, &s_info->list);
}
-static void load_output(cnode *root, void *platform,
- struct listnode *streams_output_cfg_list)
+static void load_cfg_list(cnode *root, void *platform,
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list)
{
- cnode *node = config_find(root, OUTPUTS_TAG);
- if (node == NULL) {
- ALOGE("%s: could not load output, node is NULL", __func__);
- return;
+ cnode *node = NULL;
+
+ node = config_find(root, OUTPUTS_TAG);
+ if (node != NULL) {
+ node = node->first_child;
+ while (node) {
+ ALOGV("%s: loading output %s", __func__, node->name);
+ update_streams_cfg_list(node, platform, streams_output_cfg_list);
+ node = node->next;
+ }
+ } else {
+ ALOGI("%s: could not load output, node is NULL", __func__);
}
- node = node->first_child;
- while (node) {
- ALOGV("%s: loading output %s", __func__, node->name);
- update_streams_output_cfg_list(node, platform, streams_output_cfg_list);
- node = node->next;
+ node = config_find(root, INPUTS_TAG);
+ if (node != NULL) {
+ node = node->first_child;
+ while (node) {
+ ALOGV("%s: loading input %s", __func__, node->name);
+ update_streams_cfg_list(node, platform, streams_input_cfg_list);
+ node = node->next;
+ }
+ } else {
+ ALOGI("%s: could not load input, node is NULL", __func__);
}
}
static void send_app_type_cfg(void *platform, struct mixer *mixer,
- struct listnode *streams_output_cfg_list)
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list)
{
- int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
+ size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
int length = 0, i, num_app_types = 0;
struct listnode *node;
bool update;
struct mixer_ctl *ctl = NULL;
const char *mixer_ctl_name = "App Type Config";
- struct streams_output_cfg *so_info;
+ struct streams_io_cfg *s_info = NULL;
if (!mixer) {
ALOGE("%s: mixer is null",__func__);
@@ -327,32 +353,63 @@
ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
return;
}
- if (streams_output_cfg_list == NULL) {
- app_type_cfg[length++] = 1;
- app_type_cfg[length++] = platform_get_default_app_type(platform);
+ app_type_cfg[length++] = num_app_types;
+
+ if (list_empty(streams_output_cfg_list)) {
+ app_type_cfg[length++] = platform_get_default_app_type_v2(platform, PCM_PLAYBACK);
app_type_cfg[length++] = 48000;
app_type_cfg[length++] = 16;
- mixer_ctl_set_array(ctl, app_type_cfg, length);
- return;
+ num_app_types += 1;
+ }
+ if (list_empty(streams_input_cfg_list)) {
+ app_type_cfg[length++] = platform_get_default_app_type_v2(platform, PCM_CAPTURE);
+ app_type_cfg[length++] = 48000;
+ app_type_cfg[length++] = 16;
+ num_app_types += 1;
}
- app_type_cfg[length++] = num_app_types;
list_for_each(node, streams_output_cfg_list) {
- so_info = node_to_item(node, struct streams_output_cfg, list);
+ s_info = node_to_item(node, struct streams_io_cfg, list);
update = true;
for (i=0; i<length; i=i+3) {
- if (app_type_cfg[i+1] == -1)
+ if (app_type_cfg[i+1] == 0)
break;
- else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
+ else if (app_type_cfg[i+1] == (size_t)s_info->app_type_cfg.app_type) {
+ if (app_type_cfg[i+2] < s_info->app_type_cfg.sample_rate)
+ app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
+ if (app_type_cfg[i+3] < s_info->app_type_cfg.bit_width)
+ app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
update = false;
break;
}
}
if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
- num_app_types += 1 ;
- app_type_cfg[length++] = so_info->app_type_cfg.app_type;
- app_type_cfg[length++] = so_info->app_type_cfg.sample_rate;
- app_type_cfg[length++] = so_info->app_type_cfg.bit_width;
+ num_app_types += 1;
+ app_type_cfg[length++] = s_info->app_type_cfg.app_type;
+ app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
+ app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
+ }
+ }
+ list_for_each(node, streams_input_cfg_list) {
+ s_info = node_to_item(node, struct streams_io_cfg, list);
+ update = true;
+ for (i=0; i<length; i=i+3) {
+ if (app_type_cfg[i+1] == 0)
+ break;
+ else if (app_type_cfg[i+1] == (size_t)s_info->app_type_cfg.app_type) {
+ if (app_type_cfg[i+2] < s_info->app_type_cfg.sample_rate)
+ app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
+ if (app_type_cfg[i+3] < s_info->app_type_cfg.bit_width)
+ app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
+ update = false;
+ break;
+ }
+ }
+ if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
+ num_app_types += 1;
+ app_type_cfg[length++] = s_info->app_type_cfg.app_type;
+ app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
+ app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
}
}
ALOGV("%s: num_app_types: %d", __func__, num_app_types);
@@ -362,101 +419,131 @@
}
}
-void audio_extn_utils_update_streams_output_cfg_list(void *platform,
- struct mixer *mixer,
- struct listnode *streams_output_cfg_list)
+void audio_extn_utils_update_streams_cfg_lists(void *platform,
+ struct mixer *mixer,
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list)
{
cnode *root;
- char *data;
+ char *data = NULL;
ALOGV("%s", __func__);
list_init(streams_output_cfg_list);
- data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
- if (data == NULL) {
- send_app_type_cfg(platform, mixer, NULL);
- ALOGE("%s: could not load output policy config file", __func__);
- return;
- }
+ list_init(streams_input_cfg_list);
root = config_node("", "");
if (root == NULL) {
ALOGE("cfg_list, NULL config root");
- free(data);
return;
}
- config_load(root, data);
- load_output(root, platform, streams_output_cfg_list);
+ data = (char *)load_file(AUDIO_IO_POLICY_VENDOR_CONFIG_FILE, NULL);
+ if (data == NULL) {
+ ALOGD("%s: failed to open io config file(%s), trying older config file",
+ __func__, AUDIO_IO_POLICY_VENDOR_CONFIG_FILE);
+ data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
+ if (data == NULL) {
+ send_app_type_cfg(platform, mixer,
+ streams_output_cfg_list,
+ streams_input_cfg_list);
+ ALOGE("%s: could not load io policy config!", __func__);
+ return;
+ }
+ }
- send_app_type_cfg(platform, mixer, streams_output_cfg_list);
+ config_load(root, data);
+ load_cfg_list(root, platform, streams_output_cfg_list,
+ streams_input_cfg_list);
+
+ send_app_type_cfg(platform, mixer, streams_output_cfg_list,
+ streams_input_cfg_list);
config_free(root);
free(data);
}
-void audio_extn_utils_dump_streams_output_cfg_list(
- struct listnode *streams_output_cfg_list)
+static void audio_extn_utils_dump_streams_cfg_list(
+ struct listnode *streams_cfg_list)
{
struct listnode *node_i, *node_j;
- struct streams_output_cfg *so_info;
+ struct streams_io_cfg *s_info;
struct stream_format *sf_info;
struct stream_sample_rate *ss_info;
- ALOGV("%s", __func__);
- list_for_each(node_i, streams_output_cfg_list) {
- so_info = node_to_item(node_i, struct streams_output_cfg, list);
- ALOGV("%s: flags-%d, output_sample_rate-%d, output_bit_width-%d, app_type-%d",
- __func__, so_info->flags, so_info->app_type_cfg.sample_rate,
- so_info->app_type_cfg.bit_width, so_info->app_type_cfg.app_type);
- list_for_each(node_j, &so_info->format_list) {
+
+ list_for_each(node_i, streams_cfg_list) {
+ s_info = node_to_item(node_i, struct streams_io_cfg, list);
+ ALOGV("%s: flags-%d, sample_rate-%d, bit_width-%d, app_type-%d",
+ __func__, s_info->flags.out_flags, s_info->app_type_cfg.sample_rate,
+ s_info->app_type_cfg.bit_width, s_info->app_type_cfg.app_type);
+ list_for_each(node_j, &s_info->format_list) {
sf_info = node_to_item(node_j, struct stream_format, list);
ALOGV("format-%x", sf_info->format);
}
- list_for_each(node_j, &so_info->sample_rate_list) {
+ list_for_each(node_j, &s_info->sample_rate_list) {
ss_info = node_to_item(node_j, struct stream_sample_rate, list);
ALOGV("sample rate-%d", ss_info->sample_rate);
}
}
}
-void audio_extn_utils_release_streams_output_cfg_list(
- struct listnode *streams_output_cfg_list)
+void audio_extn_utils_dump_streams_cfg_lists(
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list)
+{
+ ALOGV("%s", __func__);
+ audio_extn_utils_dump_streams_cfg_list(streams_output_cfg_list);
+ audio_extn_utils_dump_streams_cfg_list(streams_input_cfg_list);
+}
+
+static void audio_extn_utils_release_streams_cfg_list(
+ struct listnode *streams_cfg_list)
{
struct listnode *node_i, *node_j;
- struct streams_output_cfg *so_info;
+ struct streams_io_cfg *s_info;
ALOGV("%s", __func__);
- while (!list_empty(streams_output_cfg_list)) {
- node_i = list_head(streams_output_cfg_list);
- so_info = node_to_item(node_i, struct streams_output_cfg, list);
- while (!list_empty(&so_info->format_list)) {
- node_j = list_head(&so_info->format_list);
+
+ while (!list_empty(streams_cfg_list)) {
+ node_i = list_head(streams_cfg_list);
+ s_info = node_to_item(node_i, struct streams_io_cfg, list);
+ while (!list_empty(&s_info->format_list)) {
+ node_j = list_head(&s_info->format_list);
list_remove(node_j);
free(node_to_item(node_j, struct stream_format, list));
}
- while (!list_empty(&so_info->sample_rate_list)) {
- node_j = list_head(&so_info->sample_rate_list);
+ while (!list_empty(&s_info->sample_rate_list)) {
+ node_j = list_head(&s_info->sample_rate_list);
list_remove(node_j);
free(node_to_item(node_j, struct stream_sample_rate, list));
}
list_remove(node_i);
- free(node_to_item(node_i, struct streams_output_cfg, list));
+ free(node_to_item(node_i, struct streams_io_cfg, list));
}
}
-static bool set_output_cfg(struct streams_output_cfg *so_info,
- struct stream_app_type_cfg *app_type_cfg,
- uint32_t sample_rate, uint32_t bit_width)
+void audio_extn_utils_release_streams_cfg_lists(
+ struct listnode *streams_output_cfg_list,
+ struct listnode *streams_input_cfg_list)
+{
+ ALOGV("%s", __func__);
+ audio_extn_utils_release_streams_cfg_list(streams_output_cfg_list);
+ audio_extn_utils_release_streams_cfg_list(streams_input_cfg_list);
+}
+
+static bool set_app_type_cfg(struct streams_io_cfg *s_info,
+ struct stream_app_type_cfg *app_type_cfg,
+ uint32_t sample_rate, uint32_t bit_width)
{
struct listnode *node_i;
struct stream_sample_rate *ss_info;
- list_for_each(node_i, &so_info->sample_rate_list) {
+ list_for_each(node_i, &s_info->sample_rate_list) {
ss_info = node_to_item(node_i, struct stream_sample_rate, list);
if ((sample_rate <= ss_info->sample_rate) &&
- (bit_width == so_info->app_type_cfg.bit_width)) {
+ (bit_width == s_info->app_type_cfg.bit_width)) {
- app_type_cfg->app_type = so_info->app_type_cfg.app_type;
+ app_type_cfg->app_type = s_info->app_type_cfg.app_type;
app_type_cfg->sample_rate = ss_info->sample_rate;
- app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+ app_type_cfg->bit_width = s_info->app_type_cfg.bit_width;
ALOGV("%s app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
__func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
return true;
@@ -469,13 +556,13 @@
*/
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- list_for_each(node_i, &so_info->sample_rate_list) {
+ list_for_each(node_i, &s_info->sample_rate_list) {
ss_info = node_to_item(node_i, struct stream_sample_rate, list);
if ((sample_rate <= ss_info->sample_rate) &&
- (bit_width == so_info->app_type_cfg.bit_width)) {
- app_type_cfg->app_type = so_info->app_type_cfg.app_type;
+ (bit_width == s_info->app_type_cfg.bit_width)) {
+ app_type_cfg->app_type = s_info->app_type_cfg.app_type;
app_type_cfg->sample_rate = sample_rate;
- app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+ app_type_cfg->bit_width = s_info->app_type_cfg.bit_width;
ALOGV("%s Assuming sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
__func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
return true;
@@ -484,7 +571,41 @@
return false;
}
-void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+void audio_extn_utils_update_stream_input_app_type_cfg(void *platform,
+ struct listnode *streams_input_cfg_list,
+ audio_devices_t devices __unused,
+ audio_input_flags_t flags,
+ audio_format_t format,
+ uint32_t sample_rate,
+ uint32_t bit_width,
+ struct stream_app_type_cfg *app_type_cfg)
+{
+ struct listnode *node_i, *node_j;
+ struct streams_io_cfg *s_info;
+ struct stream_format *sf_info;
+
+ ALOGV("%s: flags: 0x%x, format: 0x%x sample_rate %d",
+ __func__, flags, format, sample_rate);
+
+ list_for_each(node_i, streams_input_cfg_list) {
+ s_info = node_to_item(node_i, struct streams_io_cfg, list);
+ if (s_info->flags.in_flags == flags) {
+ list_for_each(node_j, &s_info->format_list) {
+ sf_info = node_to_item(node_j, struct stream_format, list);
+ if (sf_info->format == format) {
+ if (set_app_type_cfg(s_info, app_type_cfg, sample_rate, bit_width))
+ return;
+ }
+ }
+ }
+ }
+ ALOGW("%s: App type could not be selected. Falling back to default", __func__);
+ app_type_cfg->app_type = platform_get_default_app_type_v2(platform, PCM_CAPTURE);
+ app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ app_type_cfg->bit_width = 16;
+}
+
+void audio_extn_utils_update_stream_output_app_type_cfg(void *platform,
struct listnode *streams_output_cfg_list,
audio_devices_t devices,
audio_output_flags_t flags,
@@ -495,7 +616,7 @@
struct stream_app_type_cfg *app_type_cfg)
{
struct listnode *node_i, *node_j;
- struct streams_output_cfg *so_info;
+ struct streams_io_cfg *s_info;
struct stream_format *sf_info;
char value[PROPERTY_VALUE_MAX] = {0};
@@ -543,26 +664,26 @@
ALOGV("%s: flags: %x, format: %x sample_rate %d",
__func__, flags, format, sample_rate);
list_for_each(node_i, streams_output_cfg_list) {
- so_info = node_to_item(node_i, struct streams_output_cfg, list);
- if (so_info->flags == flags) {
- list_for_each(node_j, &so_info->format_list) {
+ s_info = node_to_item(node_i, struct streams_io_cfg, list);
+ if (s_info->flags.out_flags == flags) {
+ list_for_each(node_j, &s_info->format_list) {
sf_info = node_to_item(node_j, struct stream_format, list);
if (sf_info->format == format) {
- if (set_output_cfg(so_info, app_type_cfg, sample_rate, bit_width))
+ if (set_app_type_cfg(s_info, app_type_cfg, sample_rate, bit_width))
return;
}
}
}
}
list_for_each(node_i, streams_output_cfg_list) {
- so_info = node_to_item(node_i, struct streams_output_cfg, list);
- if (so_info->flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
+ s_info = node_to_item(node_i, struct streams_io_cfg, list);
+ if (s_info->flags.out_flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
ALOGV("Compatible output profile not found.");
- app_type_cfg->app_type = so_info->app_type_cfg.app_type;
- app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
- app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+ app_type_cfg->app_type = s_info->app_type_cfg.app_type;
+ app_type_cfg->sample_rate = s_info->app_type_cfg.sample_rate;
+ app_type_cfg->bit_width = s_info->app_type_cfg.bit_width;
ALOGV("%s Default to primary output: App type: %d sample_rate %d",
- __func__, so_info->app_type_cfg.app_type, app_type_cfg->sample_rate);
+ __func__, s_info->app_type_cfg.app_type, app_type_cfg->sample_rate);
return;
}
}
@@ -586,20 +707,57 @@
return native_usecase;
}
+void audio_extn_utils_update_stream_app_type_cfg_for_usecase(
+ struct audio_device *adev,
+ struct audio_usecase *usecase)
+{
+ ALOGV("%s", __func__);
+
+ switch(usecase->type) {
+ case PCM_PLAYBACK:
+ audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
+ &adev->streams_output_cfg_list,
+ usecase->stream.out->devices,
+ usecase->stream.out->flags,
+ usecase->stream.out->format,
+ usecase->stream.out->sample_rate,
+ usecase->stream.out->bit_width,
+ usecase->stream.out->channel_mask,
+ &usecase->stream.out->app_type_cfg);
+ ALOGV("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
+ break;
+ case PCM_CAPTURE:
+ audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
+ &adev->streams_input_cfg_list,
+ usecase->stream.in->device,
+ usecase->stream.in->flags,
+ usecase->stream.in->format,
+ usecase->stream.in->sample_rate,
+ usecase->stream.in->bit_width,
+ &usecase->stream.in->app_type_cfg);
+ ALOGV("%s Selected apptype: %d", __func__, usecase->stream.in->app_type_cfg.app_type);
+ break;
+ default:
+ ALOGE("%s: app type cfg not supported for usecase type (%d)",
+ __func__, usecase->type);
+ }
+}
+
int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
struct audio_usecase *usecase)
{
char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
- int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
+ size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
+ int len = 0, rc;
struct mixer_ctl *ctl;
- int pcm_device_id = 0, acdb_dev_id, snd_device = usecase->out_snd_device;
+ int pcm_device_id, acdb_dev_id = 0, snd_device = usecase->out_snd_device;
int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
char value[PROPERTY_VALUE_MAX] = {0};
ALOGV("%s", __func__);
if (usecase->type != PCM_PLAYBACK && usecase->type != PCM_CAPTURE) {
- ALOGE("%s: not a playback or capture path, no need to cfg app type", __func__);
+ ALOGE("%s: not a playback/capture path, no need to cfg app type", __func__);
rc = 0;
goto exit_send_app_type_cfg;
}
@@ -608,20 +766,28 @@
(usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
(!is_offload_usecase(usecase->id)) &&
(usecase->type != PCM_CAPTURE)) {
- ALOGV("%s: a rx/tx path where app type cfg is not required %d", __func__, usecase->id);
+ ALOGV("%s: a rx/tx/loopback path where app type cfg is not required %d", __func__, usecase->id);
rc = 0;
goto exit_send_app_type_cfg;
}
if (usecase->type == PCM_PLAYBACK) {
snd_device = usecase->out_snd_device;
pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
+ snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+ "Audio Stream %d App Type Cfg", pcm_device_id);
+ acdb_dev_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
} else if (usecase->type == PCM_CAPTURE) {
snd_device = usecase->in_snd_device;
pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
+ snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+ "Audio Stream Capture %d App Type Cfg", pcm_device_id);
+ acdb_dev_id = platform_get_snd_device_acdb_id(usecase->in_snd_device);
}
-
- snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
- "Audio Stream %d App Type Cfg", pcm_device_id);
+ if (acdb_dev_id <= 0) {
+ ALOGE("%s: Couldn't get the acdb dev id", __func__);
+ rc = -EINVAL;
+ goto exit_send_app_type_cfg;
+ }
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
@@ -632,40 +798,25 @@
}
snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
platform_get_spkr_prot_snd_device(snd_device) : snd_device;
- acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
- if (acdb_dev_id < 0) {
- ALOGE("%s: Couldn't get the acdb dev id", __func__);
- rc = -EINVAL;
- goto exit_send_app_type_cfg;
- }
- if ((usecase->type == PCM_PLAYBACK) && (usecase->stream.out == NULL)) {
- sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
- app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
- app_type_cfg[len++] = acdb_dev_id;
- app_type_cfg[len++] = sample_rate;
- ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, __LINE__,
- platform_get_default_app_type(adev->platform),
- acdb_dev_id, sample_rate);
- } else if (usecase->type == PCM_PLAYBACK) {
- if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
- usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
- } else if ((usecase->stream.out->app_type_cfg.sample_rate == OUTPUT_SAMPLING_RATE_44100 &&
- !(audio_is_this_native_usecase(usecase))) ||
- (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
- usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
- }
+ if ((usecase->type == PCM_PLAYBACK) && (usecase->stream.out != NULL)) {
+ if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+ usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ } else if ((usecase->stream.out->app_type_cfg.sample_rate == OUTPUT_SAMPLING_RATE_44100 &&
+ !(audio_is_this_native_usecase(usecase))) ||
+ (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
+ usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ }
- sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
+ sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
- property_get("audio.playback.mch.downsample",value,"");
- if (!strncmp("true", value, sizeof("true"))) {
- if ((popcount(usecase->stream.out->channel_mask) > 2) &&
- (usecase->stream.out->app_type_cfg.sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
- !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
- sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- }
+ property_get("audio.playback.mch.downsample",value,"");
+ if (!strncmp("true", value, sizeof("true"))) {
+ if ((popcount(usecase->stream.out->channel_mask) > 2) &&
+ (usecase->stream.out->app_type_cfg.sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
+ !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
if ((24 == usecase->stream.out->bit_width) &&
(usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
@@ -698,23 +849,28 @@
} else {
app_type_cfg[len++] = sample_rate;
}
- ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, usecase->stream.out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
- } else if (usecase->type == PCM_CAPTURE) {
- app_type_cfg[len++] = platform_get_default_app_type_v2(adev->platform, usecase->type);
- app_type_cfg[len++] = acdb_dev_id;
- app_type_cfg[len++] = sample_rate;
- ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, platform_get_default_app_type_v2(adev->platform, usecase->type),
- acdb_dev_id, sample_rate);
+
+ ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, usecase->stream.out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
+
+ } else if ((usecase->type == PCM_CAPTURE) && (usecase->stream.in != NULL)) {
+ app_type_cfg[len++] = usecase->stream.in->app_type_cfg.app_type;
+ app_type_cfg[len++] = acdb_dev_id;
+ app_type_cfg[len++] = usecase->stream.in->app_type_cfg.sample_rate;
+ ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, usecase->stream.in->app_type_cfg.app_type, acdb_dev_id,
+ usecase->stream.in->app_type_cfg.sample_rate);
+ } else {
+ app_type_cfg[len++] = platform_get_default_app_type_v2(adev->platform, usecase->type);
+ app_type_cfg[len++] = acdb_dev_id;
+ app_type_cfg[len++] = sample_rate;
+ ALOGI("%s default app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, platform_get_default_app_type_v2(adev->platform, usecase->type),
+ acdb_dev_id, sample_rate);
}
mixer_ctl_set_array(ctl, app_type_cfg, len);
rc = 0;
- ALOGI("%s:becf: adm: app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__,
- platform_get_default_app_type_v2(adev->platform, usecase->type),
- acdb_dev_id, sample_rate);
exit_send_app_type_cfg:
return rc;
}
@@ -925,12 +1081,15 @@
platform_send_audio_calibration(adev->platform, usecase,
out->app_type_cfg.app_type,
usecase->stream.out->app_type_cfg.sample_rate);
- }
- if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
+ } else if (type == PCM_CAPTURE) {
+ platform_send_audio_calibration(adev->platform, usecase,
+ usecase->stream.in->app_type_cfg.app_type,
+ usecase->stream.in->app_type_cfg.sample_rate);
+ } else {
/* when app type is default. the sample rate is not used to send cal */
platform_send_audio_calibration(adev->platform, usecase,
- platform_get_default_app_type_v2(adev->platform, usecase->type),
- 48000);
+ platform_get_default_app_type_v2(adev->platform, usecase->type),
+ 48000);
}
}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index bd393f2..fa04db9 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1616,25 +1616,15 @@
usecase->in_snd_device = in_snd_device;
usecase->out_snd_device = out_snd_device;
+ audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
+ usecase);
if (usecase->type == PCM_PLAYBACK) {
- audio_extn_utils_update_stream_app_type_cfg(adev->platform,
- &adev->streams_output_cfg_list,
- usecase->stream.out->devices,
- usecase->stream.out->flags,
- usecase->stream.out->format,
- usecase->stream.out->sample_rate,
- usecase->stream.out->bit_width,
- usecase->stream.out->channel_mask,
- &usecase->stream.out->app_type_cfg);
- ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
-
/* Notify device change info to effect clients registered */
audio_extn_gef_notify_device_config(
usecase->stream.out->devices,
usecase->stream.out->channel_mask,
platform_get_snd_device_acdb_id(usecase->out_snd_device));
}
-
enable_audio_route(adev, usecase);
if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
@@ -4137,7 +4127,7 @@
/* TODO remove this hardcoding and check why width is zero*/
if (out->bit_width == 0)
out->bit_width = 16;
- audio_extn_utils_update_stream_app_type_cfg(adev->platform,
+ audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
&adev->streams_output_cfg_list,
devices, flags, format, out->sample_rate,
out->bit_width, out->channel_mask,
@@ -4771,6 +4761,11 @@
}
}
+ audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
+ &adev->streams_input_cfg_list,
+ devices, flags, in->format, in->sample_rate,
+ in->bit_width, &in->app_type_cfg);
+
/* This stream could be for sound trigger lab,
get sound trigger pcm if present */
audio_extn_sound_trigger_check_and_get_session(in);
@@ -4841,9 +4836,11 @@
if ((--audio_device_ref_count) == 0) {
audio_extn_sound_trigger_deinit(adev);
audio_extn_listen_deinit(adev);
+ audio_extn_utils_release_streams_cfg_lists(
+ &adev->streams_output_cfg_list,
+ &adev->streams_input_cfg_list);
if (audio_extn_qaf_is_enabled())
audio_extn_qaf_deinit();
- audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
audio_route_free(adev->audio_route);
audio_extn_gef_deinit();
free(adev->snd_dev_ref_cnt);
@@ -5058,8 +5055,9 @@
audio_extn_ds2_enable(adev);
*device = &adev->device.common;
- audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
- &adev->streams_output_cfg_list);
+ audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
+ &adev->streams_output_cfg_list,
+ &adev->streams_input_cfg_list);
audio_device_ref_count++;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 83ad54d..b733be8 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -268,6 +268,8 @@
int bit_width;
bool realtime;
int af_period_multiplier;
+ struct stream_app_type_cfg app_type_cfg;
+
struct audio_device *dev;
};
@@ -291,6 +293,8 @@
audio_devices_t devices;
snd_device_t out_snd_device;
snd_device_t in_snd_device;
+ struct stream_app_type_cfg out_app_type_cfg;
+ struct stream_app_type_cfg in_app_type_cfg;
union stream_ptr stream;
};
@@ -309,9 +313,14 @@
uint32_t sample_rate;
};
-struct streams_output_cfg {
+typedef union {
+ audio_output_flags_t out_flags;
+ audio_input_flags_t in_flags;
+} audio_io_flags_t;
+
+struct streams_io_cfg {
struct listnode list;
- audio_output_flags_t flags;
+ audio_io_flags_t flags;
struct listnode format_list;
struct listnode sample_rate_list;
struct stream_app_type_cfg app_type_cfg;
@@ -346,6 +355,7 @@
int *snd_dev_ref_cnt;
struct listnode usecase_list;
struct listnode streams_output_cfg_list;
+ struct listnode streams_input_cfg_list;
struct audio_route *audio_route;
int acdb_settings;
bool speaker_lr_swap;