summaryrefslogtreecommitdiff
path: root/audio/hal/audio_extn/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/hal/audio_extn/utils.c')
-rw-r--r--audio/hal/audio_extn/utils.c569
1 files changed, 569 insertions, 0 deletions
diff --git a/audio/hal/audio_extn/utils.c b/audio/hal/audio_extn/utils.c
new file mode 100644
index 0000000..273a194
--- /dev/null
+++ b/audio/hal/audio_extn/utils.c
@@ -0,0 +1,569 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "audio_hw_utils"
+/* #define LOG_NDEBUG 0 */
+
+#include <errno.h>
+#include <cutils/properties.h>
+#include <cutils/config_utils.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/str_parms.h>
+#include <cutils/log.h>
+#include <cutils/misc.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "audio_extn.h"
+
+#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
+
+#define OUTPUTS_TAG "outputs"
+
+#define DYNAMIC_VALUE_TAG "dynamic"
+#define FLAGS_TAG "flags"
+#define FORMATS_TAG "formats"
+#define SAMPLING_RATES_TAG "sampling_rates"
+#define BIT_WIDTH_TAG "bit_width"
+#define APP_TYPE_TAG "app_type"
+
+#define STRING_TO_ENUM(string) { #string, string }
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+struct string_to_enum {
+ const char *name;
+ uint32_t value;
+};
+
+const struct string_to_enum s_flag_name_to_enum_table[] = {
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+#ifdef INCALL_MUSIC_ENABLED
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
+#endif
+#ifdef COMPRESS_VOIP_ENABLED
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+#endif
+};
+
+const struct string_to_enum s_format_name_to_enum_table[] = {
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_MP3),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC),
+ STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
+ STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
+ STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
+ STRING_TO_ENUM(AUDIO_FORMAT_AC3),
+ STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
+#ifdef FORMATS_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_DTS),
+ STRING_TO_ENUM(AUDIO_FORMAT_DTS_LBR),
+ STRING_TO_ENUM(AUDIO_FORMAT_WMA),
+ STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
+ STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
+ STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
+ STRING_TO_ENUM(AUDIO_FORMAT_MP2),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
+#endif
+};
+
+static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
+ const char *name)
+{
+ size_t i;
+ for (i = 0; i < size; i++) {
+ if (strcmp(table[i].name, name) == 0) {
+ ALOGV("%s found %s", __func__, table[i].name);
+ return table[i].value;
+ }
+ }
+ return 0;
+}
+
+static audio_output_flags_t parse_flag_names(char *name)
+{
+ uint32_t flag = 0;
+ char *flag_name = strtok(name, "|");
+ while (flag_name != NULL) {
+ if (strlen(flag_name) != 0) {
+ flag |= string_to_enum(s_flag_name_to_enum_table,
+ ARRAY_SIZE(s_flag_name_to_enum_table),
+ flag_name);
+ }
+ flag_name = strtok(NULL, "|");
+ }
+
+ ALOGV("parse_flag_names: flag - %d", flag);
+ return (audio_output_flags_t)flag;
+}
+
+static void parse_format_names(char *name, struct streams_output_cfg *so_info)
+{
+ struct stream_format *sf_info = NULL;
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
+ return;
+
+ list_init(&so_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);
+ ALOGV("%s: format - %d", __func__, format);
+ if (format != 0) {
+ sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
+ if (sf_info == NULL)
+ break; /* return whatever was parsed */
+
+ sf_info->format = format;
+ list_add_tail(&so_info->format_list, &sf_info->list);
+ }
+ str = strtok(NULL, "|");
+ }
+}
+
+static void parse_sample_rate_names(char *name, struct streams_output_cfg *so_info)
+{
+ struct stream_sample_rate *ss_info = NULL;
+ uint32_t sample_rate = 48000;
+ char *str = strtok(name, "|");
+
+ if (str != NULL && 0 == strcmp(str, DYNAMIC_VALUE_TAG))
+ return;
+
+ list_init(&so_info->sample_rate_list);
+ while (str != NULL) {
+ sample_rate = (uint32_t)strtol(str, (char **)NULL, 10);
+ ALOGV("%s: sample_rate - %d", __func__, sample_rate);
+ if (0 != sample_rate) {
+ ss_info = (struct stream_sample_rate *)calloc(1, sizeof(struct stream_sample_rate));
+ if (ss_info == NULL)
+ break; /* return whatever was parsed */
+
+ ss_info->sample_rate = sample_rate;
+ list_add_tail(&so_info->sample_rate_list, &ss_info->list);
+ }
+ str = strtok(NULL, "|");
+ }
+}
+
+static int parse_bit_width_names(char *name)
+{
+ int bit_width = 16;
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+ bit_width = (int)strtol(str, (char **)NULL, 10);
+
+ ALOGV("%s: bit_width - %d", __func__, bit_width);
+ return bit_width;
+}
+
+static int parse_app_type_names(void *platform, char *name)
+{
+ int app_type = platform_get_default_app_type(platform);
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+ app_type = (int)strtol(str, (char **)NULL, 10);
+
+ ALOGV("%s: app_type - %d", __func__, app_type);
+ return app_type;
+}
+
+static void update_streams_output_cfg_list(cnode *root, void *platform,
+ struct listnode *streams_output_cfg_list)
+{
+ cnode *node = root->first_child;
+ struct streams_output_cfg *so_info;
+
+ ALOGV("%s", __func__);
+ so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
+
+ if (!so_info) {
+ ALOGE("failed to allocate mem for so_info list element");
+ return;
+ }
+
+ while (node) {
+ if (strcmp(node->name, FLAGS_TAG) == 0) {
+ so_info->flags = parse_flag_names((char *)node->value);
+ } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+ parse_format_names((char *)node->value, so_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);
+ } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
+ so_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);
+ }
+ node = node->next;
+ }
+ list_add_tail(streams_output_cfg_list, &so_info->list);
+}
+
+static void load_output(cnode *root, void *platform,
+ struct listnode *streams_output_cfg_list)
+{
+ cnode *node = config_find(root, OUTPUTS_TAG);
+ if (node == NULL) {
+ ALOGE("%s: could not load output, node is NULL", __func__);
+ return;
+ }
+
+ 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;
+ }
+}
+
+static void send_app_type_cfg(void *platform, struct mixer *mixer,
+ struct listnode *streams_output_cfg_list)
+{
+ int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
+ 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;
+
+ if (!mixer) {
+ ALOGE("%s: mixer is null",__func__);
+ return;
+ }
+ ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
+ if (!ctl) {
+ 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++] = 48000;
+ app_type_cfg[length++] = 16;
+ mixer_ctl_set_array(ctl, app_type_cfg, length);
+ return;
+ }
+
+ 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);
+ update = true;
+ for (i=0; i<length; i=i+3) {
+ if (app_type_cfg[i+1] == -1)
+ break;
+ else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
+ 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;
+ }
+ }
+ ALOGV("%s: num_app_types: %d", __func__, num_app_types);
+ if (num_app_types) {
+ app_type_cfg[0] = num_app_types;
+ mixer_ctl_set_array(ctl, app_type_cfg, length);
+ }
+}
+
+void audio_extn_utils_update_streams_output_cfg_list(void *platform,
+ struct mixer *mixer,
+ struct listnode *streams_output_cfg_list)
+{
+ cnode *root;
+ char *data;
+
+ 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;
+ }
+
+ root = config_node("", "");
+ if (root == NULL) {
+ ALOGE("cfg_list, NULL config root");
+ return;
+ }
+
+ config_load(root, data);
+ load_output(root, platform, streams_output_cfg_list);
+
+ send_app_type_cfg(platform, mixer, streams_output_cfg_list);
+}
+
+void audio_extn_utils_dump_streams_output_cfg_list(
+ struct listnode *streams_output_cfg_list)
+{
+ int i=0;
+ struct listnode *node_i, *node_j;
+ struct streams_output_cfg *so_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) {
+ 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) {
+ 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)
+{
+ struct listnode *node_i, *node_j;
+ struct streams_output_cfg *so_info;
+ struct stream_format *sf_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);
+ 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);
+ 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));
+ }
+}
+
+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)
+ {
+ struct listnode *node_i;
+ struct stream_sample_rate *ss_info;
+ list_for_each(node_i, &so_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;
+ app_type_cfg->sample_rate = ss_info->sample_rate;
+ app_type_cfg->bit_width = so_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;
+ }
+ }
+ /*
+ * Reiterate through the list assuming dafault sample rate.
+ * Handles scenario where input sample rate is higher
+ * than all sample rates in list for the input bit width.
+ */
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ list_for_each(node_i, &so_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;
+ app_type_cfg->sample_rate = sample_rate;
+ app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+ ALOGV("%s Assuming default 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;
+ }
+ }
+ return false;
+}
+
+void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+ struct listnode *streams_output_cfg_list,
+ audio_devices_t devices,
+ audio_output_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, *node_k;
+ struct streams_output_cfg *so_info;
+ struct stream_format *sf_info;
+ struct stream_sample_rate *ss_info;
+
+ if ((24 == bit_width) &&
+ (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+ sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
+ }
+
+ 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) {
+ 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))
+ 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) {
+ 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;
+ 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);
+ return;
+ }
+ }
+ ALOGW("%s: App type could not be selected. Falling back to default", __func__);
+ app_type_cfg->app_type = platform_get_default_app_type(platform);
+ app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ app_type_cfg->bit_width = 16;
+}
+
+int audio_extn_utils_send_app_type_cfg(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;
+ struct stream_out *out;
+ struct audio_device *adev;
+ struct mixer_ctl *ctl;
+ int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
+ int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+
+ ALOGV("%s", __func__);
+
+ if (usecase->type != PCM_PLAYBACK) {
+ ALOGV("%s: not a playback path, no need to cfg app type", __func__);
+ rc = 0;
+ goto exit_send_app_type_cfg;
+ }
+ if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
+ (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
+ (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
+ (usecase->id != USECASE_AUDIO_PLAYBACK_OFFLOAD)) {
+ ALOGV("%s: a playback path where app type cfg is not required", __func__);
+ rc = 0;
+ goto exit_send_app_type_cfg;
+ }
+ out = usecase->stream.out;
+ adev = out->dev;
+
+ snd_device = usecase->out_snd_device;
+
+ pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+
+ snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+ "Audio Stream %d App Type Cfg", pcm_device_id);
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
+ mixer_ctl_name);
+ rc = -EINVAL;
+ goto exit_send_app_type_cfg;
+ }
+ snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+ audio_extn_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 ((24 == usecase->stream.out->bit_width) &&
+ (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+ sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ } else {
+ sample_rate = out->app_type_cfg.sample_rate;
+ }
+
+ app_type_cfg[len++] = out->app_type_cfg.app_type;
+ app_type_cfg[len++] = acdb_dev_id;
+ app_type_cfg[len++] = sample_rate;
+
+ mixer_ctl_set_array(ctl, app_type_cfg, len);
+ ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
+ rc = 0;
+exit_send_app_type_cfg:
+ return rc;
+}
+
+void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
+ struct audio_usecase *usecase)
+{
+ int type = usecase->type;
+
+ if (type == PCM_PLAYBACK) {
+ struct stream_out *out = usecase->stream.out;
+ int snd_device = usecase->out_snd_device;
+ snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+ audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
+ platform_send_audio_calibration(adev->platform, usecase,
+ out->app_type_cfg.app_type,
+ out->app_type_cfg.sample_rate);
+ }
+ if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
+ /* 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(adev->platform),
+ 48000);
+ }
+}
+