blob: e2052515ddfdb824ebd2f0d78d6b0272708c4c59 [file] [log] [blame]
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07001/*
2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_utils"
21/* #define LOG_NDEBUG 0 */
22
23#include <errno.h>
24#include <cutils/properties.h>
25#include <cutils/config_utils.h>
26#include <stdlib.h>
27#include <dlfcn.h>
28#include <cutils/str_parms.h>
29#include <cutils/log.h>
30#include <cutils/misc.h>
31
32#include "audio_hw.h"
33#include "platform.h"
34#include "platform_api.h"
35#include "audio_extn.h"
Narsinga Rao Chella212e2542014-11-17 19:57:04 -080036#include "voice.h"
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070037
38#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
39
40#define OUTPUTS_TAG "outputs"
41
42#define DYNAMIC_VALUE_TAG "dynamic"
43#define FLAGS_TAG "flags"
44#define FORMATS_TAG "formats"
45#define SAMPLING_RATES_TAG "sampling_rates"
46#define BIT_WIDTH_TAG "bit_width"
47#define APP_TYPE_TAG "app_type"
48
49#define STRING_TO_ENUM(string) { #string, string }
50#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
51
52struct string_to_enum {
53 const char *name;
54 uint32_t value;
55};
56
57const struct string_to_enum s_flag_name_to_enum_table[] = {
58 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
59 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
60 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
61 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
62 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
63 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
64#ifdef INCALL_MUSIC_ENABLED
65 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
66#endif
67#ifdef COMPRESS_VOIP_ENABLED
68 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
69#endif
70};
71
72const struct string_to_enum s_format_name_to_enum_table[] = {
73 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
74 STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
75 STRING_TO_ENUM(AUDIO_FORMAT_MP3),
76 STRING_TO_ENUM(AUDIO_FORMAT_AAC),
77 STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
Mingming Yinae3530f2014-07-03 16:50:18 -070078 STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
79 STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070080 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
Mingming Yinae3530f2014-07-03 16:50:18 -070081 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
82#ifdef FORMATS_ENABLED
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070083 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
84 STRING_TO_ENUM(AUDIO_FORMAT_DTS_LBR),
85 STRING_TO_ENUM(AUDIO_FORMAT_WMA),
86 STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
87 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070088 STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
89 STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
90 STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
91 STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
92 STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
93 STRING_TO_ENUM(AUDIO_FORMAT_MP2),
94 STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
95 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
96 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
Amit Shekhar6f461b12014-08-01 14:52:58 -070097 STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070098#endif
99};
100
101static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
102 const char *name)
103{
104 size_t i;
105 for (i = 0; i < size; i++) {
106 if (strcmp(table[i].name, name) == 0) {
107 ALOGV("%s found %s", __func__, table[i].name);
108 return table[i].value;
109 }
110 }
111 return 0;
112}
113
114static audio_output_flags_t parse_flag_names(char *name)
115{
116 uint32_t flag = 0;
117 char *flag_name = strtok(name, "|");
118 while (flag_name != NULL) {
119 if (strlen(flag_name) != 0) {
120 flag |= string_to_enum(s_flag_name_to_enum_table,
121 ARRAY_SIZE(s_flag_name_to_enum_table),
122 flag_name);
123 }
124 flag_name = strtok(NULL, "|");
125 }
126
127 ALOGV("parse_flag_names: flag - %d", flag);
128 return (audio_output_flags_t)flag;
129}
130
131static void parse_format_names(char *name, struct streams_output_cfg *so_info)
132{
133 struct stream_format *sf_info = NULL;
134 char *str = strtok(name, "|");
135
136 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
137 return;
138
139 list_init(&so_info->format_list);
140 while (str != NULL) {
141 audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
142 ARRAY_SIZE(s_format_name_to_enum_table), str);
143 ALOGV("%s: format - %d", __func__, format);
144 if (format != 0) {
145 sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700146 if (sf_info == NULL)
147 break; /* return whatever was parsed */
148
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700149 sf_info->format = format;
150 list_add_tail(&so_info->format_list, &sf_info->list);
151 }
152 str = strtok(NULL, "|");
153 }
154}
155
Amit Shekhar6f461b12014-08-01 14:52:58 -0700156static void parse_sample_rate_names(char *name, struct streams_output_cfg *so_info)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700157{
Amit Shekhar6f461b12014-08-01 14:52:58 -0700158 struct stream_sample_rate *ss_info = NULL;
159 uint32_t sample_rate = 48000;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700160 char *str = strtok(name, "|");
161
Amit Shekhar6f461b12014-08-01 14:52:58 -0700162 if (str != NULL && 0 == strcmp(str, DYNAMIC_VALUE_TAG))
163 return;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700164
Amit Shekhar6f461b12014-08-01 14:52:58 -0700165 list_init(&so_info->sample_rate_list);
166 while (str != NULL) {
167 sample_rate = (uint32_t)strtol(str, (char **)NULL, 10);
168 ALOGV("%s: sample_rate - %d", __func__, sample_rate);
169 if (0 != sample_rate) {
170 ss_info = (struct stream_sample_rate *)calloc(1, sizeof(struct stream_sample_rate));
171 ss_info->sample_rate = sample_rate;
172 list_add_tail(&so_info->sample_rate_list, &ss_info->list);
173 }
174 str = strtok(NULL, "|");
175 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700176}
177
178static int parse_bit_width_names(char *name)
179{
180 int bit_width = 16;
181 char *str = strtok(name, "|");
182
183 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
184 bit_width = (int)strtol(str, (char **)NULL, 10);
185
186 ALOGV("%s: bit_width - %d", __func__, bit_width);
187 return bit_width;
188}
189
190static int parse_app_type_names(void *platform, char *name)
191{
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700192 int app_type = platform_get_default_app_type(platform);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700193 char *str = strtok(name, "|");
194
195 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
196 app_type = (int)strtol(str, (char **)NULL, 10);
197
198 ALOGV("%s: app_type - %d", __func__, app_type);
199 return app_type;
200}
201
202static void update_streams_output_cfg_list(cnode *root, void *platform,
203 struct listnode *streams_output_cfg_list)
204{
205 cnode *node = root->first_child;
206 struct streams_output_cfg *so_info;
207
208 ALOGV("%s", __func__);
209 so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700210
211 if (!so_info) {
212 ALOGE("failed to allocate mem for so_info list element");
213 return;
214 }
215
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700216 while (node) {
217 if (strcmp(node->name, FLAGS_TAG) == 0) {
218 so_info->flags = parse_flag_names((char *)node->value);
219 } else if (strcmp(node->name, FORMATS_TAG) == 0) {
220 parse_format_names((char *)node->value, so_info);
221 } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700222 so_info->app_type_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
223 parse_sample_rate_names((char *)node->value, so_info);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700224 } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
225 so_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
226 } else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
227 so_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
228 }
229 node = node->next;
230 }
231 list_add_tail(streams_output_cfg_list, &so_info->list);
232}
233
234static void load_output(cnode *root, void *platform,
235 struct listnode *streams_output_cfg_list)
236{
237 cnode *node = config_find(root, OUTPUTS_TAG);
238 if (node == NULL) {
239 ALOGE("%s: could not load output, node is NULL", __func__);
240 return;
241 }
242
243 node = node->first_child;
244 while (node) {
245 ALOGV("%s: loading output %s", __func__, node->name);
246 update_streams_output_cfg_list(node, platform, streams_output_cfg_list);
247 node = node->next;
248 }
249}
250
251static void send_app_type_cfg(void *platform, struct mixer *mixer,
252 struct listnode *streams_output_cfg_list)
253{
254 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
255 int length = 0, i, num_app_types = 0;
256 struct listnode *node;
257 bool update;
258 struct mixer_ctl *ctl = NULL;
259 const char *mixer_ctl_name = "App Type Config";
260 struct streams_output_cfg *so_info;
261
262 if (!mixer) {
263 ALOGE("%s: mixer is null",__func__);
264 return;
265 }
266 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
267 if (!ctl) {
268 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
269 return;
270 }
271 if (streams_output_cfg_list == NULL) {
272 app_type_cfg[length++] = 1;
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700273 app_type_cfg[length++] = platform_get_default_app_type(platform);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700274 app_type_cfg[length++] = 48000;
275 app_type_cfg[length++] = 16;
276 mixer_ctl_set_array(ctl, app_type_cfg, length);
277 return;
278 }
279
280 app_type_cfg[length++] = num_app_types;
281 list_for_each(node, streams_output_cfg_list) {
282 so_info = node_to_item(node, struct streams_output_cfg, list);
283 update = true;
284 for (i=0; i<length; i=i+3) {
285 if (app_type_cfg[i+1] == -1)
286 break;
287 else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
288 update = false;
289 break;
290 }
291 }
292 if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
293 num_app_types += 1 ;
294 app_type_cfg[length++] = so_info->app_type_cfg.app_type;
295 app_type_cfg[length++] = so_info->app_type_cfg.sample_rate;
296 app_type_cfg[length++] = so_info->app_type_cfg.bit_width;
297 }
298 }
299 ALOGV("%s: num_app_types: %d", __func__, num_app_types);
300 if (num_app_types) {
301 app_type_cfg[0] = num_app_types;
302 mixer_ctl_set_array(ctl, app_type_cfg, length);
303 }
304}
305
306void audio_extn_utils_update_streams_output_cfg_list(void *platform,
307 struct mixer *mixer,
308 struct listnode *streams_output_cfg_list)
309{
310 cnode *root;
311 char *data;
312
313 ALOGV("%s", __func__);
314 list_init(streams_output_cfg_list);
315 data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
316 if (data == NULL) {
317 send_app_type_cfg(platform, mixer, NULL);
318 ALOGE("%s: could not load output policy config file", __func__);
319 return;
320 }
321
322 root = config_node("", "");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700323 if (root == NULL) {
324 ALOGE("cfg_list, NULL config root");
325 return;
326 }
327
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700328 config_load(root, data);
329 load_output(root, platform, streams_output_cfg_list);
330
331 send_app_type_cfg(platform, mixer, streams_output_cfg_list);
332}
333
334void audio_extn_utils_dump_streams_output_cfg_list(
335 struct listnode *streams_output_cfg_list)
336{
337 int i=0;
338 struct listnode *node_i, *node_j;
339 struct streams_output_cfg *so_info;
340 struct stream_format *sf_info;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700341 struct stream_sample_rate *ss_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700342 ALOGV("%s", __func__);
343 list_for_each(node_i, streams_output_cfg_list) {
344 so_info = node_to_item(node_i, struct streams_output_cfg, list);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700345 ALOGV("%s: flags-%d, output_sample_rate-%d, output_bit_width-%d, app_type-%d",
346 __func__, so_info->flags, so_info->app_type_cfg.sample_rate,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700347 so_info->app_type_cfg.bit_width, so_info->app_type_cfg.app_type);
348 list_for_each(node_j, &so_info->format_list) {
349 sf_info = node_to_item(node_j, struct stream_format, list);
350 ALOGV("format-%x", sf_info->format);
351 }
Amit Shekhar6f461b12014-08-01 14:52:58 -0700352 list_for_each(node_j, &so_info->sample_rate_list) {
353 ss_info = node_to_item(node_j, struct stream_sample_rate, list);
354 ALOGV("sample rate-%d", ss_info->sample_rate);
355 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700356 }
357}
358
359void audio_extn_utils_release_streams_output_cfg_list(
360 struct listnode *streams_output_cfg_list)
361{
362 struct listnode *node_i, *node_j;
363 struct streams_output_cfg *so_info;
364 struct stream_format *sf_info;
365
366 ALOGV("%s", __func__);
367 while (!list_empty(streams_output_cfg_list)) {
368 node_i = list_head(streams_output_cfg_list);
369 so_info = node_to_item(node_i, struct streams_output_cfg, list);
370 while (!list_empty(&so_info->format_list)) {
371 node_j = list_head(&so_info->format_list);
372 list_remove(node_j);
373 free(node_to_item(node_j, struct stream_format, list));
374 }
Amit Shekhar6f461b12014-08-01 14:52:58 -0700375 while (!list_empty(&so_info->sample_rate_list)) {
376 node_j = list_head(&so_info->sample_rate_list);
377 list_remove(node_j);
378 free(node_to_item(node_j, struct stream_sample_rate, list));
379 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700380 list_remove(node_i);
381 free(node_to_item(node_i, struct streams_output_cfg, list));
382 }
383}
384
Amit Shekhar6f461b12014-08-01 14:52:58 -0700385static bool set_output_cfg(struct streams_output_cfg *so_info,
386 struct stream_app_type_cfg *app_type_cfg,
387 uint32_t sample_rate, uint32_t bit_width)
388 {
389 struct listnode *node_i;
390 struct stream_sample_rate *ss_info;
391 list_for_each(node_i, &so_info->sample_rate_list) {
392 ss_info = node_to_item(node_i, struct stream_sample_rate, list);
393 if ((sample_rate <= ss_info->sample_rate) &&
394 (bit_width == so_info->app_type_cfg.bit_width)) {
395 app_type_cfg->app_type = so_info->app_type_cfg.app_type;
396 app_type_cfg->sample_rate = ss_info->sample_rate;
397 app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
398 ALOGV("%s app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
399 __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
400 return true;
401 }
402 }
403 /*
404 * Reiterate through the list assuming dafault sample rate.
405 * Handles scenario where input sample rate is higher
406 * than all sample rates in list for the input bit width.
407 */
408 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
409 list_for_each(node_i, &so_info->sample_rate_list) {
410 ss_info = node_to_item(node_i, struct stream_sample_rate, list);
411 if ((sample_rate <= ss_info->sample_rate) &&
412 (bit_width == so_info->app_type_cfg.bit_width)) {
413 app_type_cfg->app_type = so_info->app_type_cfg.app_type;
414 app_type_cfg->sample_rate = sample_rate;
415 app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
416 ALOGV("%s Assuming default sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
417 __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
418 return true;
419 }
420 }
421 return false;
422}
423
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700424void audio_extn_utils_update_stream_app_type_cfg(void *platform,
425 struct listnode *streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700426 audio_devices_t devices,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700427 audio_output_flags_t flags,
428 audio_format_t format,
Amit Shekhar6f461b12014-08-01 14:52:58 -0700429 uint32_t sample_rate,
430 uint32_t bit_width,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700431 struct stream_app_type_cfg *app_type_cfg)
432{
Amit Shekhar6f461b12014-08-01 14:52:58 -0700433 struct listnode *node_i, *node_j, *node_k;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700434 struct streams_output_cfg *so_info;
435 struct stream_format *sf_info;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700436 struct stream_sample_rate *ss_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700437
Amit Shekhar1d896042014-10-03 13:16:09 -0700438 if ((24 == bit_width) &&
439 (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
Amit Shekhar5a39c912014-10-14 15:39:30 -0700440 int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
441 if (-ENOSYS != bw)
442 bit_width = (uint32_t)bw;
Amit Shekhar1d896042014-10-03 13:16:09 -0700443 sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
444 ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
445 }
446
447 ALOGV("%s: flags: %x, format: %x sample_rate %d",
448 __func__, flags, format, sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700449 list_for_each(node_i, streams_output_cfg_list) {
450 so_info = node_to_item(node_i, struct streams_output_cfg, list);
451 if (so_info->flags == flags) {
452 list_for_each(node_j, &so_info->format_list) {
453 sf_info = node_to_item(node_j, struct stream_format, list);
454 if (sf_info->format == format) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700455 if (set_output_cfg(so_info, app_type_cfg, sample_rate, bit_width))
456 return;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700457 }
458 }
459 }
460 }
461 list_for_each(node_i, streams_output_cfg_list) {
462 so_info = node_to_item(node_i, struct streams_output_cfg, list);
463 if (so_info->flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
464 ALOGV("Compatible output profile not found.");
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700465 app_type_cfg->app_type = so_info->app_type_cfg.app_type;
466 app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
467 app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700468 ALOGV("%s Default to primary output: App type: %d sample_rate %d",
469 __func__, so_info->app_type_cfg.app_type, app_type_cfg->sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700470 return;
471 }
472 }
473 ALOGW("%s: App type could not be selected. Falling back to default", __func__);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700474 app_type_cfg->app_type = platform_get_default_app_type(platform);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700475 app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700476 app_type_cfg->bit_width = 16;
477}
478
479int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase)
480{
481 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
482 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
Anish Kumarc8599f22014-07-20 09:36:07 -0700483 struct stream_out *out;
484 struct audio_device *adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700485 struct mixer_ctl *ctl;
486 int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530487 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700488
489 ALOGV("%s", __func__);
490
491 if (usecase->type != PCM_PLAYBACK) {
492 ALOGV("%s: not a playback path, no need to cfg app type", __func__);
493 rc = 0;
494 goto exit_send_app_type_cfg;
495 }
496 if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
497 (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
498 (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
Alexy Joseph2f89cfa2014-10-06 12:15:01 -0700499 (!is_offload_usecase(usecase->id))) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700500 ALOGV("%s: a playback path where app type cfg is not required", __func__);
501 rc = 0;
502 goto exit_send_app_type_cfg;
503 }
Anish Kumarc8599f22014-07-20 09:36:07 -0700504 out = usecase->stream.out;
505 adev = out->dev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700506
507 snd_device = usecase->out_snd_device;
508
509 pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
510
511 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
512 "Audio Stream %d App Type Cfg", pcm_device_id);
513
514 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
515 if (!ctl) {
516 ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
517 mixer_ctl_name);
518 rc = -EINVAL;
519 goto exit_send_app_type_cfg;
520 }
521 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
522 audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
523 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
524 if (acdb_dev_id < 0) {
525 ALOGE("%s: Couldn't get the acdb dev id", __func__);
526 rc = -EINVAL;
527 goto exit_send_app_type_cfg;
528 }
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530529
530 if ((24 == usecase->stream.out->bit_width) &&
Amit Shekhar1d896042014-10-03 13:16:09 -0700531 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530532 sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
533 } else {
534 sample_rate = out->app_type_cfg.sample_rate;
535 }
536
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700537 app_type_cfg[len++] = out->app_type_cfg.app_type;
538 app_type_cfg[len++] = acdb_dev_id;
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530539 app_type_cfg[len++] = sample_rate;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700540
541 mixer_ctl_set_array(ctl, app_type_cfg, len);
Amit Shekhar278e3362014-09-08 14:08:19 -0700542 ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530543 __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700544 rc = 0;
545exit_send_app_type_cfg:
546 return rc;
547}
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700548
549void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
550 struct audio_usecase *usecase)
551{
552 int type = usecase->type;
553
554 if (type == PCM_PLAYBACK) {
555 struct stream_out *out = usecase->stream.out;
556 int snd_device = usecase->out_snd_device;
557 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
558 audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
559 platform_send_audio_calibration(adev->platform, usecase->out_snd_device,
560 out->app_type_cfg.app_type,
561 out->app_type_cfg.sample_rate);
562 }
563 if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
Narsinga Rao Chella212e2542014-11-17 19:57:04 -0800564 if ((type == PCM_CAPTURE) & voice_is_in_call_rec_stream(usecase->stream.in)) {
565 snd_device_t incall_record_snd_device =
566 voice_get_incall_rec_snd_device(usecase->in_snd_device);
567 platform_send_audio_calibration(adev->platform, incall_record_snd_device,
568 platform_get_default_app_type(adev->platform),
569 48000);
570 } else {
571 /* when app type is default. the sample rate is not used to send cal */
572 platform_send_audio_calibration(adev->platform, usecase->in_snd_device,
573 platform_get_default_app_type(adev->platform),
574 48000);
575 }
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700576 }
577}
578