blob: 90b39b5671b29a2e1eaf0d6e2ae219a908eb04b0 [file] [log] [blame]
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07001/*
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002 * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003 * 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
Ashish Jain81eb2a82015-05-13 10:52:34 +053038#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
39#ifdef HDMI_PASSTHROUGH_ENABLED
40#include "audio_parsers.h"
41#endif
42#endif
43
Yamit Mehtaa0d653a2016-11-25 20:33:25 +053044#ifdef LINUX_ENABLED
45#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/etc/audio_output_policy.conf"
46#else
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070047#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
Yamit Mehtaa0d653a2016-11-25 20:33:25 +053048#endif
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070049
50#define OUTPUTS_TAG "outputs"
51
52#define DYNAMIC_VALUE_TAG "dynamic"
53#define FLAGS_TAG "flags"
54#define FORMATS_TAG "formats"
55#define SAMPLING_RATES_TAG "sampling_rates"
56#define BIT_WIDTH_TAG "bit_width"
57#define APP_TYPE_TAG "app_type"
58
59#define STRING_TO_ENUM(string) { #string, string }
60#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
61
Ben Rombergera04fabc2014-11-14 12:16:03 -080062#define BASE_TABLE_SIZE 64
63#define MAX_BASEINDEX_LEN 256
64
Ashish Jain81eb2a82015-05-13 10:52:34 +053065#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
66#define PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
67#define NON_LPCM (1<<1) /* 0 = audio, 1 = non-audio */
68#define SR_44100 (0<<0) /* 44.1kHz */
69#define SR_NOTID (1<<0) /* non indicated */
70#define SR_48000 (2<<0) /* 48kHz */
71#define SR_32000 (3<<0) /* 32kHz */
72#define SR_22050 (4<<0) /* 22.05kHz */
73#define SR_24000 (6<<0) /* 24kHz */
74#define SR_88200 (8<<0) /* 88.2kHz */
75#define SR_96000 (10<<0) /* 96kHz */
76#define SR_176400 (12<<0) /* 176.4kHz */
77#define SR_192000 (14<<0) /* 192kHz */
78
79#endif
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070080struct string_to_enum {
81 const char *name;
82 uint32_t value;
83};
84
85const struct string_to_enum s_flag_name_to_enum_table[] = {
86 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
vivek mehta0ea887a2015-08-26 14:01:20 -070087 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070088 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
89 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
90 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
91 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
92 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -070093 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070094#ifdef INCALL_MUSIC_ENABLED
95 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
96#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -070097 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070098};
99
100const struct string_to_enum s_format_name_to_enum_table[] = {
Ashish Jain83a6cc22016-06-28 14:34:17 +0530101 STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700102 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
Ashish Jain5106d362016-05-11 19:23:33 +0530103 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
104 STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
Ashish Jainf1eaa582016-05-23 20:54:24 +0530105 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700106 STRING_TO_ENUM(AUDIO_FORMAT_MP3),
107 STRING_TO_ENUM(AUDIO_FORMAT_AAC),
108 STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
Mingming Yinae3530f2014-07-03 16:50:18 -0700109 STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
110 STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700111 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
Mingming Yinae3530f2014-07-03 16:50:18 -0700112 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700113 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530114 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
115#ifdef AUDIO_EXTN_FORMATS_ENABLED
116 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700117 STRING_TO_ENUM(AUDIO_FORMAT_WMA),
118 STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
119 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700120 STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
121 STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
122 STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
123 STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
124 STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
125 STRING_TO_ENUM(AUDIO_FORMAT_MP2),
126 STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
Amit Shekhar6f461b12014-08-01 14:52:58 -0700127 STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530128 STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
129 STRING_TO_ENUM(AUDIO_FORMAT_APE),
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -0700130 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Alexy Josephcd8eaed2014-12-11 12:46:53 -0800131 STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
132 STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
133 STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
Manish Dewangana6fc5442015-08-24 20:30:31 +0530134 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS),
Ashish Jaine513a872015-11-19 17:00:56 +0530135 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LC),
136 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1),
137 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2),
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530138 STRING_TO_ENUM(AUDIO_FORMAT_DSD),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700139#endif
140};
141
Ben Rombergera04fabc2014-11-14 12:16:03 -0800142static char bTable[BASE_TABLE_SIZE] = {
143 'A','B','C','D','E','F','G','H','I','J','K','L',
144 'M','N','O','P','Q','R','S','T','U','V','W','X',
145 'Y','Z','a','b','c','d','e','f','g','h','i','j',
146 'k','l','m','n','o','p','q','r','s','t','u','v',
147 'w','x','y','z','0','1','2','3','4','5','6','7',
148 '8','9','+','/'
149};
150
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700151static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
152 const char *name)
153{
154 size_t i;
155 for (i = 0; i < size; i++) {
156 if (strcmp(table[i].name, name) == 0) {
157 ALOGV("%s found %s", __func__, table[i].name);
158 return table[i].value;
159 }
160 }
161 return 0;
162}
163
164static audio_output_flags_t parse_flag_names(char *name)
165{
166 uint32_t flag = 0;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800167 char *last_r;
168 char *flag_name = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700169 while (flag_name != NULL) {
170 if (strlen(flag_name) != 0) {
171 flag |= string_to_enum(s_flag_name_to_enum_table,
172 ARRAY_SIZE(s_flag_name_to_enum_table),
173 flag_name);
174 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800175 flag_name = strtok_r(NULL, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700176 }
177
178 ALOGV("parse_flag_names: flag - %d", flag);
179 return (audio_output_flags_t)flag;
180}
181
182static void parse_format_names(char *name, struct streams_output_cfg *so_info)
183{
184 struct stream_format *sf_info = NULL;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800185 char *last_r;
186 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700187
188 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
189 return;
190
191 list_init(&so_info->format_list);
192 while (str != NULL) {
193 audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
194 ARRAY_SIZE(s_format_name_to_enum_table), str);
195 ALOGV("%s: format - %d", __func__, format);
196 if (format != 0) {
197 sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700198 if (sf_info == NULL)
199 break; /* return whatever was parsed */
200
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700201 sf_info->format = format;
202 list_add_tail(&so_info->format_list, &sf_info->list);
203 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800204 str = strtok_r(NULL, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700205 }
206}
207
Amit Shekhar6f461b12014-08-01 14:52:58 -0700208static void parse_sample_rate_names(char *name, struct streams_output_cfg *so_info)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700209{
Amit Shekhar6f461b12014-08-01 14:52:58 -0700210 struct stream_sample_rate *ss_info = NULL;
211 uint32_t sample_rate = 48000;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800212 char *last_r;
213 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700214
Amit Shekhar6f461b12014-08-01 14:52:58 -0700215 if (str != NULL && 0 == strcmp(str, DYNAMIC_VALUE_TAG))
216 return;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700217
Amit Shekhar6f461b12014-08-01 14:52:58 -0700218 list_init(&so_info->sample_rate_list);
219 while (str != NULL) {
220 sample_rate = (uint32_t)strtol(str, (char **)NULL, 10);
221 ALOGV("%s: sample_rate - %d", __func__, sample_rate);
222 if (0 != sample_rate) {
223 ss_info = (struct stream_sample_rate *)calloc(1, sizeof(struct stream_sample_rate));
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800224 if (!ss_info) {
225 ALOGE("%s: memory allocation failure", __func__);
226 return;
227 }
Amit Shekhar6f461b12014-08-01 14:52:58 -0700228 ss_info->sample_rate = sample_rate;
229 list_add_tail(&so_info->sample_rate_list, &ss_info->list);
230 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800231 str = strtok_r(NULL, "|", &last_r);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700232 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700233}
234
235static int parse_bit_width_names(char *name)
236{
237 int bit_width = 16;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800238 char *last_r;
239 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700240
241 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
242 bit_width = (int)strtol(str, (char **)NULL, 10);
243
244 ALOGV("%s: bit_width - %d", __func__, bit_width);
245 return bit_width;
246}
247
248static int parse_app_type_names(void *platform, char *name)
249{
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700250 int app_type = platform_get_default_app_type(platform);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800251 char *last_r;
252 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700253
254 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
255 app_type = (int)strtol(str, (char **)NULL, 10);
256
257 ALOGV("%s: app_type - %d", __func__, app_type);
258 return app_type;
259}
260
261static void update_streams_output_cfg_list(cnode *root, void *platform,
262 struct listnode *streams_output_cfg_list)
263{
264 cnode *node = root->first_child;
265 struct streams_output_cfg *so_info;
266
267 ALOGV("%s", __func__);
268 so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700269
270 if (!so_info) {
271 ALOGE("failed to allocate mem for so_info list element");
272 return;
273 }
274
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700275 while (node) {
276 if (strcmp(node->name, FLAGS_TAG) == 0) {
277 so_info->flags = parse_flag_names((char *)node->value);
278 } else if (strcmp(node->name, FORMATS_TAG) == 0) {
279 parse_format_names((char *)node->value, so_info);
280 } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700281 so_info->app_type_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
282 parse_sample_rate_names((char *)node->value, so_info);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700283 } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
284 so_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
285 } else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
286 so_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
287 }
288 node = node->next;
289 }
290 list_add_tail(streams_output_cfg_list, &so_info->list);
291}
292
293static void load_output(cnode *root, void *platform,
294 struct listnode *streams_output_cfg_list)
295{
296 cnode *node = config_find(root, OUTPUTS_TAG);
297 if (node == NULL) {
298 ALOGE("%s: could not load output, node is NULL", __func__);
299 return;
300 }
301
302 node = node->first_child;
303 while (node) {
304 ALOGV("%s: loading output %s", __func__, node->name);
305 update_streams_output_cfg_list(node, platform, streams_output_cfg_list);
306 node = node->next;
307 }
308}
309
310static void send_app_type_cfg(void *platform, struct mixer *mixer,
311 struct listnode *streams_output_cfg_list)
312{
313 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
314 int length = 0, i, num_app_types = 0;
315 struct listnode *node;
316 bool update;
317 struct mixer_ctl *ctl = NULL;
318 const char *mixer_ctl_name = "App Type Config";
319 struct streams_output_cfg *so_info;
320
321 if (!mixer) {
322 ALOGE("%s: mixer is null",__func__);
323 return;
324 }
325 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
326 if (!ctl) {
327 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
328 return;
329 }
330 if (streams_output_cfg_list == NULL) {
331 app_type_cfg[length++] = 1;
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700332 app_type_cfg[length++] = platform_get_default_app_type(platform);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700333 app_type_cfg[length++] = 48000;
334 app_type_cfg[length++] = 16;
335 mixer_ctl_set_array(ctl, app_type_cfg, length);
336 return;
337 }
338
339 app_type_cfg[length++] = num_app_types;
340 list_for_each(node, streams_output_cfg_list) {
341 so_info = node_to_item(node, struct streams_output_cfg, list);
342 update = true;
343 for (i=0; i<length; i=i+3) {
344 if (app_type_cfg[i+1] == -1)
345 break;
346 else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
347 update = false;
348 break;
349 }
350 }
351 if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
352 num_app_types += 1 ;
353 app_type_cfg[length++] = so_info->app_type_cfg.app_type;
354 app_type_cfg[length++] = so_info->app_type_cfg.sample_rate;
355 app_type_cfg[length++] = so_info->app_type_cfg.bit_width;
356 }
357 }
358 ALOGV("%s: num_app_types: %d", __func__, num_app_types);
359 if (num_app_types) {
360 app_type_cfg[0] = num_app_types;
361 mixer_ctl_set_array(ctl, app_type_cfg, length);
362 }
363}
364
365void audio_extn_utils_update_streams_output_cfg_list(void *platform,
366 struct mixer *mixer,
367 struct listnode *streams_output_cfg_list)
368{
369 cnode *root;
370 char *data;
371
372 ALOGV("%s", __func__);
373 list_init(streams_output_cfg_list);
374 data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
375 if (data == NULL) {
376 send_app_type_cfg(platform, mixer, NULL);
377 ALOGE("%s: could not load output policy config file", __func__);
378 return;
379 }
380
381 root = config_node("", "");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700382 if (root == NULL) {
383 ALOGE("cfg_list, NULL config root");
Alexy Josephaee4fdd2016-01-29 13:02:07 -0800384 free(data);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700385 return;
386 }
387
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700388 config_load(root, data);
389 load_output(root, platform, streams_output_cfg_list);
390
391 send_app_type_cfg(platform, mixer, streams_output_cfg_list);
Alexy Josephaee4fdd2016-01-29 13:02:07 -0800392
393 config_free(root);
394 free(data);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700395}
396
397void audio_extn_utils_dump_streams_output_cfg_list(
398 struct listnode *streams_output_cfg_list)
399{
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700400 struct listnode *node_i, *node_j;
401 struct streams_output_cfg *so_info;
402 struct stream_format *sf_info;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700403 struct stream_sample_rate *ss_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700404 ALOGV("%s", __func__);
405 list_for_each(node_i, streams_output_cfg_list) {
406 so_info = node_to_item(node_i, struct streams_output_cfg, list);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700407 ALOGV("%s: flags-%d, output_sample_rate-%d, output_bit_width-%d, app_type-%d",
408 __func__, so_info->flags, so_info->app_type_cfg.sample_rate,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700409 so_info->app_type_cfg.bit_width, so_info->app_type_cfg.app_type);
410 list_for_each(node_j, &so_info->format_list) {
411 sf_info = node_to_item(node_j, struct stream_format, list);
412 ALOGV("format-%x", sf_info->format);
413 }
Amit Shekhar6f461b12014-08-01 14:52:58 -0700414 list_for_each(node_j, &so_info->sample_rate_list) {
415 ss_info = node_to_item(node_j, struct stream_sample_rate, list);
416 ALOGV("sample rate-%d", ss_info->sample_rate);
417 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700418 }
419}
420
421void audio_extn_utils_release_streams_output_cfg_list(
422 struct listnode *streams_output_cfg_list)
423{
424 struct listnode *node_i, *node_j;
425 struct streams_output_cfg *so_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700426
427 ALOGV("%s", __func__);
428 while (!list_empty(streams_output_cfg_list)) {
429 node_i = list_head(streams_output_cfg_list);
430 so_info = node_to_item(node_i, struct streams_output_cfg, list);
431 while (!list_empty(&so_info->format_list)) {
432 node_j = list_head(&so_info->format_list);
433 list_remove(node_j);
434 free(node_to_item(node_j, struct stream_format, list));
435 }
Amit Shekhar6f461b12014-08-01 14:52:58 -0700436 while (!list_empty(&so_info->sample_rate_list)) {
437 node_j = list_head(&so_info->sample_rate_list);
438 list_remove(node_j);
439 free(node_to_item(node_j, struct stream_sample_rate, list));
440 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700441 list_remove(node_i);
442 free(node_to_item(node_i, struct streams_output_cfg, list));
443 }
444}
445
Amit Shekhar6f461b12014-08-01 14:52:58 -0700446static bool set_output_cfg(struct streams_output_cfg *so_info,
447 struct stream_app_type_cfg *app_type_cfg,
448 uint32_t sample_rate, uint32_t bit_width)
449 {
450 struct listnode *node_i;
451 struct stream_sample_rate *ss_info;
452 list_for_each(node_i, &so_info->sample_rate_list) {
453 ss_info = node_to_item(node_i, struct stream_sample_rate, list);
454 if ((sample_rate <= ss_info->sample_rate) &&
455 (bit_width == so_info->app_type_cfg.bit_width)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -0700456
Amit Shekhar6f461b12014-08-01 14:52:58 -0700457 app_type_cfg->app_type = so_info->app_type_cfg.app_type;
458 app_type_cfg->sample_rate = ss_info->sample_rate;
459 app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
460 ALOGV("%s app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
461 __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
462 return true;
463 }
464 }
465 /*
466 * Reiterate through the list assuming dafault sample rate.
467 * Handles scenario where input sample rate is higher
468 * than all sample rates in list for the input bit width.
469 */
470 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800471
Amit Shekhar6f461b12014-08-01 14:52:58 -0700472 list_for_each(node_i, &so_info->sample_rate_list) {
473 ss_info = node_to_item(node_i, struct stream_sample_rate, list);
474 if ((sample_rate <= ss_info->sample_rate) &&
475 (bit_width == so_info->app_type_cfg.bit_width)) {
476 app_type_cfg->app_type = so_info->app_type_cfg.app_type;
477 app_type_cfg->sample_rate = sample_rate;
478 app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800479 ALOGV("%s Assuming sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
Amit Shekhar6f461b12014-08-01 14:52:58 -0700480 __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
481 return true;
482 }
483 }
484 return false;
485}
486
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700487void audio_extn_utils_update_stream_app_type_cfg(void *platform,
488 struct listnode *streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700489 audio_devices_t devices,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700490 audio_output_flags_t flags,
491 audio_format_t format,
Amit Shekhar6f461b12014-08-01 14:52:58 -0700492 uint32_t sample_rate,
493 uint32_t bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +0530494 audio_channel_mask_t channel_mask,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700495 struct stream_app_type_cfg *app_type_cfg)
496{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530497 struct listnode *node_i, *node_j;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700498 struct streams_output_cfg *so_info;
499 struct stream_format *sf_info;
Manish Dewangan837dc462015-05-27 10:17:41 +0530500 char value[PROPERTY_VALUE_MAX] = {0};
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700501
Ashish Jain058165c2016-09-28 23:18:48 +0530502 if ((bit_width >= 24) &&
Amit Shekhar1d896042014-10-03 13:16:09 -0700503 (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
Amit Shekhar5a39c912014-10-14 15:39:30 -0700504 int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
505 if (-ENOSYS != bw)
506 bit_width = (uint32_t)bw;
Amit Shekhar1d896042014-10-03 13:16:09 -0700507 sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
508 ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
509 }
510
Manish Dewangan837dc462015-05-27 10:17:41 +0530511 property_get("audio.playback.mch.downsample",value,"");
512 if (!strncmp("true", value, sizeof("true"))) {
513 if ((popcount(channel_mask) > 2) &&
514 (sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
515 !(flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)) {
516 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
517 ALOGD("%s: MCH session defaulting sample rate to %d",
518 __func__, sample_rate);
519 }
520 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521
522 /* Set sampling rate to 176.4 for DSD64
523 * and 352.8Khz for DSD128.
524 * Set Bit Width to 16. output will be 16 bit
525 * post DoP in ASM.
526 */
527 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH) &&
528 (format == AUDIO_FORMAT_DSD)) {
529 bit_width = 16;
530 if (sample_rate == INPUT_SAMPLING_RATE_DSD64)
531 sample_rate = OUTPUT_SAMPLING_RATE_DSD64;
532 else if (sample_rate == INPUT_SAMPLING_RATE_DSD128)
533 sample_rate = OUTPUT_SAMPLING_RATE_DSD128;
534 }
535
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530536 if(devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
537 //TODO: Handle fractional sampling rate configuration for LL
538 audio_extn_a2dp_get_apptype_params(&sample_rate, &bit_width);
539 ALOGI("%s using %d sampling rate %d bit width for A2DP CoPP",
540 __func__, sample_rate, bit_width);
541 }
542
Amit Shekhar1d896042014-10-03 13:16:09 -0700543 ALOGV("%s: flags: %x, format: %x sample_rate %d",
544 __func__, flags, format, sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700545 list_for_each(node_i, streams_output_cfg_list) {
546 so_info = node_to_item(node_i, struct streams_output_cfg, list);
547 if (so_info->flags == flags) {
548 list_for_each(node_j, &so_info->format_list) {
549 sf_info = node_to_item(node_j, struct stream_format, list);
550 if (sf_info->format == format) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700551 if (set_output_cfg(so_info, app_type_cfg, sample_rate, bit_width))
552 return;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700553 }
554 }
555 }
556 }
557 list_for_each(node_i, streams_output_cfg_list) {
558 so_info = node_to_item(node_i, struct streams_output_cfg, list);
559 if (so_info->flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
560 ALOGV("Compatible output profile not found.");
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700561 app_type_cfg->app_type = so_info->app_type_cfg.app_type;
562 app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
563 app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700564 ALOGV("%s Default to primary output: App type: %d sample_rate %d",
565 __func__, so_info->app_type_cfg.app_type, app_type_cfg->sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700566 return;
567 }
568 }
569 ALOGW("%s: App type could not be selected. Falling back to default", __func__);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700570 app_type_cfg->app_type = platform_get_default_app_type(platform);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700571 app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700572 app_type_cfg->bit_width = 16;
573}
574
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530575static bool audio_is_this_native_usecase(struct audio_usecase *uc)
576{
577 bool native_usecase = false;
578 struct stream_out *out = (struct stream_out*) uc->stream.out;
579
580 if (PCM_PLAYBACK == uc->type && out != NULL &&
581 NATIVE_AUDIO_MODE_INVALID != platform_get_native_support() &&
582 is_offload_usecase(uc->id) &&
583 (out->sample_rate == OUTPUT_SAMPLING_RATE_44100))
584 native_usecase = true;
585
586 return native_usecase;
587}
588
Ben Romberger1fafdde2015-09-09 19:43:15 -0700589int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
590 struct audio_usecase *usecase)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700591{
592 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
593 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700594 struct mixer_ctl *ctl;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530595 int pcm_device_id = 0, acdb_dev_id, snd_device = usecase->out_snd_device;
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530596 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Manish Dewangan837dc462015-05-27 10:17:41 +0530597 char value[PROPERTY_VALUE_MAX] = {0};
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700598
599 ALOGV("%s", __func__);
600
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530601 if (usecase->type != PCM_PLAYBACK && usecase->type != PCM_CAPTURE) {
602 ALOGE("%s: not a playback or capture path, no need to cfg app type", __func__);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700603 rc = 0;
604 goto exit_send_app_type_cfg;
605 }
606 if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
607 (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
608 (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530609 (!is_offload_usecase(usecase->id)) &&
610 (usecase->type != PCM_CAPTURE)) {
Ben Romberger1fafdde2015-09-09 19:43:15 -0700611 ALOGV("%s: a rx/tx path where app type cfg is not required %d", __func__, usecase->id);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700612 rc = 0;
613 goto exit_send_app_type_cfg;
614 }
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530615 if (usecase->type == PCM_PLAYBACK) {
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530616 snd_device = usecase->out_snd_device;
Ben Romberger1fafdde2015-09-09 19:43:15 -0700617 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
618 } else if (usecase->type == PCM_CAPTURE) {
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530619 snd_device = usecase->in_snd_device;
Ben Romberger1fafdde2015-09-09 19:43:15 -0700620 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530621 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700622
623 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
624 "Audio Stream %d App Type Cfg", pcm_device_id);
625
626 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
627 if (!ctl) {
628 ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
629 mixer_ctl_name);
630 rc = -EINVAL;
631 goto exit_send_app_type_cfg;
632 }
633 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800634 platform_get_spkr_prot_snd_device(snd_device) : snd_device;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700635 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
636 if (acdb_dev_id < 0) {
637 ALOGE("%s: Couldn't get the acdb dev id", __func__);
638 rc = -EINVAL;
639 goto exit_send_app_type_cfg;
640 }
Ashish Jainc02430d2016-01-04 10:42:43 +0530641 if ((usecase->type == PCM_PLAYBACK) && (usecase->stream.out == NULL)) {
642 sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
643 app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
644 app_type_cfg[len++] = acdb_dev_id;
645 app_type_cfg[len++] = sample_rate;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530646 ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
647 __func__, __LINE__,
648 platform_get_default_app_type(adev->platform),
649 acdb_dev_id, sample_rate);
Ashish Jainc02430d2016-01-04 10:42:43 +0530650 } else if (usecase->type == PCM_PLAYBACK) {
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530651
Sidipotu Ashokfdd505a2016-02-11 10:31:38 +0530652 if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Ashish Jainc02430d2016-01-04 10:42:43 +0530653 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Venkata Narendra Kumar Gutta4bd09d02016-01-29 15:31:04 +0530654 } else if ((usecase->stream.out->app_type_cfg.sample_rate == OUTPUT_SAMPLING_RATE_44100 &&
655 !(audio_is_this_native_usecase(usecase))) ||
656 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
657 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ashish Jainc02430d2016-01-04 10:42:43 +0530658 }
Venkata Narendra Kumar Gutta4bd09d02016-01-29 15:31:04 +0530659
Ashish Jainc02430d2016-01-04 10:42:43 +0530660 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
Manish Dewangan837dc462015-05-27 10:17:41 +0530661
Ashish Jainc02430d2016-01-04 10:42:43 +0530662 property_get("audio.playback.mch.downsample",value,"");
663 if (!strncmp("true", value, sizeof("true"))) {
664 if ((popcount(usecase->stream.out->channel_mask) > 2) &&
665 (usecase->stream.out->app_type_cfg.sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
666 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
667 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
668 }
669
Mingming Yin21854652016-04-13 11:54:02 -0700670 if ((24 == usecase->stream.out->bit_width) &&
671 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
672 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ashish Jaina052e572016-11-07 16:41:07 +0530673 } else if ((snd_device == SND_DEVICE_OUT_HDMI ||
674 snd_device == SND_DEVICE_OUT_USB_HEADSET ||
675 snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
676 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
677 /*
678 * To best utlize DSP, check if the stream sample rate is supported/multiple of
679 * configured device sample rate, if not update the COPP rate to be equal to the
680 * device sample rate, else open COPP at stream sample rate
681 */
682 platform_check_and_update_copp_sample_rate(adev->platform, snd_device,
683 usecase->stream.out->sample_rate,
684 &usecase->stream.out->app_type_cfg.sample_rate);
Mingming Yin21854652016-04-13 11:54:02 -0700685 } else if ((snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
686 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
687 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
688 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
689 }
690 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
691
692 app_type_cfg[len++] = usecase->stream.out->app_type_cfg.app_type;
693 app_type_cfg[len++] = acdb_dev_id;
694 if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
695 (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530696 && audio_extn_passthru_is_passthrough_stream(usecase->stream.out)) {
Mingming Yin21854652016-04-13 11:54:02 -0700697 app_type_cfg[len++] = sample_rate * 4;
698 } else {
699 app_type_cfg[len++] = sample_rate;
700 }
701 ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
702 __func__, usecase->stream.out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
Ashish Jainc02430d2016-01-04 10:42:43 +0530703 } else if (usecase->type == PCM_CAPTURE) {
704 app_type_cfg[len++] = platform_get_default_app_type_v2(adev->platform, usecase->type);
705 app_type_cfg[len++] = acdb_dev_id;
706 app_type_cfg[len++] = sample_rate;
707 ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d",
708 __func__, platform_get_default_app_type_v2(adev->platform, usecase->type),
709 acdb_dev_id, sample_rate);
710 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530711
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700712 mixer_ctl_set_array(ctl, app_type_cfg, len);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700713 rc = 0;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530714 ALOGI("%s:becf: adm: app_type %d, acdb_dev_id %d, sample_rate %d",
715 __func__,
716 platform_get_default_app_type_v2(adev->platform, usecase->type),
717 acdb_dev_id, sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700718exit_send_app_type_cfg:
719 return rc;
720}
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700721
Preetam Singh Ranawat9519e9c2015-11-18 16:05:55 +0530722int read_line_from_file(const char *path, char *buf, size_t count)
723{
724 char * fgets_ret;
725 FILE * fd;
726 int rv;
727
728 fd = fopen(path, "r");
729 if (fd == NULL)
730 return -1;
731
732 fgets_ret = fgets(buf, (int)count, fd);
733 if (NULL != fgets_ret) {
734 rv = (int)strlen(buf);
735 } else {
736 rv = ferror(fd);
737 }
738 fclose(fd);
739
740 return rv;
741}
742
Ashish Jainf1eaa582016-05-23 20:54:24 +0530743/*Translates ALSA formats to AOSP PCM formats*/
744audio_format_t alsa_format_to_hal(uint32_t alsa_format)
745{
746 audio_format_t format;
747
748 switch(alsa_format) {
749 case SNDRV_PCM_FORMAT_S16_LE:
750 format = AUDIO_FORMAT_PCM_16_BIT;
751 break;
752 case SNDRV_PCM_FORMAT_S24_3LE:
753 format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
754 break;
755 case SNDRV_PCM_FORMAT_S24_LE:
756 format = AUDIO_FORMAT_PCM_8_24_BIT;
757 break;
758 case SNDRV_PCM_FORMAT_S32_LE:
759 format = AUDIO_FORMAT_PCM_32_BIT;
760 break;
761 default:
762 ALOGW("Incorrect ALSA format");
763 format = AUDIO_FORMAT_INVALID;
764 }
765 return format;
766}
767
768/*Translates hal format (AOSP) to alsa formats*/
769uint32_t hal_format_to_alsa(audio_format_t hal_format)
770{
771 uint32_t alsa_format;
772
773 switch (hal_format) {
774 case AUDIO_FORMAT_PCM_32_BIT: {
775 if (platform_supports_true_32bit())
776 alsa_format = SNDRV_PCM_FORMAT_S32_LE;
777 else
778 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
779 }
780 break;
781 case AUDIO_FORMAT_PCM_8_BIT:
782 alsa_format = SNDRV_PCM_FORMAT_S8;
783 break;
784 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
785 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
786 break;
787 case AUDIO_FORMAT_PCM_8_24_BIT: {
788 if (platform_supports_true_32bit())
789 alsa_format = SNDRV_PCM_FORMAT_S32_LE;
790 else
791 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
792 }
793 break;
794 case AUDIO_FORMAT_PCM_FLOAT:
795 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
796 break;
797 default:
798 case AUDIO_FORMAT_PCM_16_BIT:
799 alsa_format = SNDRV_PCM_FORMAT_S16_LE;
800 break;
801 }
802 return alsa_format;
803}
804
Ashish Jain83a6cc22016-06-28 14:34:17 +0530805/*Translates PCM formats to AOSP formats*/
806audio_format_t pcm_format_to_hal(uint32_t pcm_format)
807{
808 audio_format_t format = AUDIO_FORMAT_INVALID;
809
810 switch(pcm_format) {
811 case PCM_FORMAT_S16_LE:
812 format = AUDIO_FORMAT_PCM_16_BIT;
813 break;
814 case PCM_FORMAT_S24_3LE:
815 format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
816 break;
817 case PCM_FORMAT_S24_LE:
818 format = AUDIO_FORMAT_PCM_8_24_BIT;
819 break;
820 case PCM_FORMAT_S32_LE:
821 format = AUDIO_FORMAT_PCM_32_BIT;
822 break;
823 default:
824 ALOGW("Incorrect PCM format");
825 format = AUDIO_FORMAT_INVALID;
826 }
827 return format;
828}
829
830/*Translates hal format (AOSP) to alsa formats*/
831uint32_t hal_format_to_pcm(audio_format_t hal_format)
832{
833 uint32_t pcm_format;
834
835 switch (hal_format) {
836 case AUDIO_FORMAT_PCM_32_BIT:
837 case AUDIO_FORMAT_PCM_8_24_BIT:
838 case AUDIO_FORMAT_PCM_FLOAT: {
839 if (platform_supports_true_32bit())
840 pcm_format = PCM_FORMAT_S32_LE;
841 else
842 pcm_format = PCM_FORMAT_S24_3LE;
843 }
844 break;
845 case AUDIO_FORMAT_PCM_8_BIT:
846 pcm_format = PCM_FORMAT_S8;
847 break;
848 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
849 pcm_format = PCM_FORMAT_S24_3LE;
850 break;
851 default:
852 case AUDIO_FORMAT_PCM_16_BIT:
853 pcm_format = PCM_FORMAT_S16_LE;
854 break;
855 }
856 return pcm_format;
857}
858
Ashish Jainf1eaa582016-05-23 20:54:24 +0530859uint32_t get_alsa_fragment_size(uint32_t bytes_per_sample,
860 uint32_t sample_rate,
861 uint32_t noOfChannels)
862{
863 uint32_t fragment_size = 0;
864 uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
865
866 fragment_size = (pcm_offload_time
867 * sample_rate
868 * bytes_per_sample
869 * noOfChannels)/1000;
870 if (fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
871 fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
872 else if (fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
873 fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
874 /*To have same PCM samples for all channels, the buffer size requires to
875 *be multiple of (number of channels * bytes per sample)
876 *For writes to succeed, the buffer must be written at address which is multiple of 32
877 */
878 fragment_size = ALIGN(fragment_size, (bytes_per_sample * noOfChannels * 32));
879
880 ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
881 return fragment_size;
882}
883
884/* Calculates the fragment size required to configure compress session.
885 * Based on the alsa format selected, decide if conversion is needed in
886
887 * HAL ( e.g. convert AUDIO_FORMAT_PCM_FLOAT input format to
888 * AUDIO_FORMAT_PCM_24_BIT_PACKED before writing to the compress driver.
889 */
890void audio_extn_utils_update_direct_pcm_fragment_size(struct stream_out *out)
891{
Ashish Jain83a6cc22016-06-28 14:34:17 +0530892 audio_format_t dst_format = out->hal_op_format;
893 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +0530894 uint32_t hal_op_bytes_per_sample = audio_bytes_per_sample(dst_format);
895 uint32_t hal_ip_bytes_per_sample = audio_bytes_per_sample(src_format);
896
897 out->compr_config.fragment_size =
898 get_alsa_fragment_size(hal_op_bytes_per_sample,
899 out->sample_rate,
900 popcount(out->channel_mask));
901
902 if ((src_format != dst_format) &&
903 hal_op_bytes_per_sample != hal_ip_bytes_per_sample) {
904
Ashish Jain83a6cc22016-06-28 14:34:17 +0530905 out->hal_fragment_size =
Ashish Jainf1eaa582016-05-23 20:54:24 +0530906 ((out->compr_config.fragment_size * hal_ip_bytes_per_sample) /
907 hal_op_bytes_per_sample);
908 ALOGI("enable conversion hal_input_fragment_size is %d src_format %x dst_format %x",
Ashish Jain83a6cc22016-06-28 14:34:17 +0530909 out->hal_fragment_size, src_format, dst_format);
Ashish Jainf1eaa582016-05-23 20:54:24 +0530910 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +0530911 out->hal_fragment_size = out->compr_config.fragment_size;
Ashish Jainf1eaa582016-05-23 20:54:24 +0530912 }
913}
914
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700915void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
916 struct audio_usecase *usecase)
917{
918 int type = usecase->type;
919
920 if (type == PCM_PLAYBACK) {
921 struct stream_out *out = usecase->stream.out;
922 int snd_device = usecase->out_snd_device;
923 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800924 platform_get_spkr_prot_snd_device(snd_device) : snd_device;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +0530925 platform_send_audio_calibration(adev->platform, usecase,
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700926 out->app_type_cfg.app_type,
Preetam Singh Ranawat61716b12015-12-14 11:55:24 +0530927 usecase->stream.out->app_type_cfg.sample_rate);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700928 }
929 if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +0530930 /* when app type is default. the sample rate is not used to send cal */
931 platform_send_audio_calibration(adev->platform, usecase,
Srikanth Uyyalaa1e32352015-10-09 14:48:04 +0530932 platform_get_default_app_type_v2(adev->platform, usecase->type),
933 48000);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700934 }
935}
936
Ben Rombergera04fabc2014-11-14 12:16:03 -0800937// Base64 Encode and Decode
938// Not all features supported. This must be used only with following conditions.
939// Decode Modes: Support with and without padding
940// CRLF not handling. So no CRLF in string to decode.
941// Encode Modes: Supports only padding
942int b64decode(char *inp, int ilen, uint8_t* outp)
943{
944 int i, j, k, ii, num;
945 int rem, pcnt;
946 uint32_t res=0;
947 uint8_t getIndex[MAX_BASEINDEX_LEN];
948 uint8_t tmp, cflag;
949
950 if(inp == NULL || outp == NULL || ilen <= 0) {
951 ALOGE("[%s] received NULL pointer or zero length",__func__);
952 return -1;
953 }
954
955 memset(getIndex, MAX_BASEINDEX_LEN-1, sizeof(getIndex));
956 for(i=0;i<BASE_TABLE_SIZE;i++) {
957 getIndex[(uint8_t)bTable[i]] = (uint8_t)i;
958 }
959 getIndex[(uint8_t)'=']=0;
960
961 j=0;k=0;
962 num = ilen/4;
963 rem = ilen%4;
964 if(rem==0)
965 num = num-1;
966 cflag=0;
967 for(i=0; i<num; i++) {
968 res=0;
969 for(ii=0;ii<4;ii++) {
970 res = res << 6;
971 tmp = getIndex[(uint8_t)inp[j++]];
972 res = res | tmp;
973 cflag = cflag | tmp;
974 }
975 outp[k++] = (res >> 16)&0xFF;
976 outp[k++] = (res >> 8)&0xFF;
977 outp[k++] = res & 0xFF;
978 }
979
980 // Handle last bytes special
981 pcnt=0;
982 if(rem == 0) {
983 //With padding or full data
984 res = 0;
985 for(ii=0;ii<4;ii++) {
986 if(inp[j] == '=')
987 pcnt++;
988 res = res << 6;
989 tmp = getIndex[(uint8_t)inp[j++]];
990 res = res | tmp;
991 cflag = cflag | tmp;
992 }
993 outp[k++] = res >> 16;
994 if(pcnt == 2)
995 goto done;
996 outp[k++] = (res>>8)&0xFF;
997 if(pcnt == 1)
998 goto done;
999 outp[k++] = res&0xFF;
1000 } else {
1001 //without padding
1002 res = 0;
1003 for(i=0;i<rem;i++) {
1004 res = res << 6;
1005 tmp = getIndex[(uint8_t)inp[j++]];
1006 res = res | tmp;
1007 cflag = cflag | tmp;
1008 }
1009 for(i=rem;i<4;i++) {
1010 res = res << 6;
1011 pcnt++;
1012 }
1013 outp[k++] = res >> 16;
1014 if(pcnt == 2)
1015 goto done;
1016 outp[k++] = (res>>8)&0xFF;
1017 if(pcnt == 1)
1018 goto done;
1019 outp[k++] = res&0xFF;
1020 }
1021done:
1022 if(cflag == 0xFF) {
1023 ALOGE("[%s] base64 decode failed. Invalid character found %s",
1024 __func__, inp);
1025 return 0;
1026 }
1027 return k;
1028}
1029
1030int b64encode(uint8_t *inp, int ilen, char* outp)
1031{
1032 int i,j,k, num;
1033 int rem=0;
1034 uint32_t res=0;
1035
1036 if(inp == NULL || outp == NULL || ilen<=0) {
1037 ALOGE("[%s] received NULL pointer or zero input length",__func__);
1038 return -1;
1039 }
1040
1041 num = ilen/3;
1042 rem = ilen%3;
1043 j=0;k=0;
1044 for(i=0; i<num; i++) {
1045 //prepare index
1046 res = inp[j++]<<16;
1047 res = res | inp[j++]<<8;
1048 res = res | inp[j++];
1049 //get output map from index
1050 outp[k++] = (char) bTable[(res>>18)&0x3F];
1051 outp[k++] = (char) bTable[(res>>12)&0x3F];
1052 outp[k++] = (char) bTable[(res>>6)&0x3F];
1053 outp[k++] = (char) bTable[res&0x3F];
1054 }
1055
1056 switch(rem) {
1057 case 1:
1058 res = inp[j++]<<16;
1059 outp[k++] = (char) bTable[res>>18];
1060 outp[k++] = (char) bTable[(res>>12)&0x3F];
1061 //outp[k++] = '=';
1062 //outp[k++] = '=';
1063 break;
1064 case 2:
1065 res = inp[j++]<<16;
1066 res = res | inp[j++]<<8;
1067 outp[k++] = (char) bTable[res>>18];
1068 outp[k++] = (char) bTable[(res>>12)&0x3F];
1069 outp[k++] = (char) bTable[(res>>6)&0x3F];
1070 //outp[k++] = '=';
1071 break;
1072 default:
1073 break;
1074 }
Ben Rombergera04fabc2014-11-14 12:16:03 -08001075 outp[k] = '\0';
1076 return k;
1077}
Ashish Jain81eb2a82015-05-13 10:52:34 +05301078
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301079
1080int audio_extn_utils_get_codec_version(const char *snd_card_name,
1081 int card_num,
1082 char *codec_version)
1083{
1084 char procfs_path[50];
1085 FILE *fp;
1086
1087 if (strstr(snd_card_name, "tasha")) {
1088 snprintf(procfs_path, sizeof(procfs_path),
1089 "/proc/asound/card%d/codecs/tasha/version", card_num);
1090 if ((fp = fopen(procfs_path, "r")) != NULL) {
1091 fgets(codec_version, CODEC_VERSION_MAX_LENGTH, fp);
1092 fclose(fp);
1093 } else {
1094 ALOGE("%s: ERROR. cannot open %s", __func__, procfs_path);
1095 return -ENOENT;
1096 }
1097 ALOGD("%s: codec version %s", __func__, codec_version);
1098 }
1099
1100 return 0;
1101}
1102
1103
Ashish Jain81eb2a82015-05-13 10:52:34 +05301104#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
1105
1106void get_default_compressed_channel_status(
1107 unsigned char *channel_status)
1108{
Ashish Jain81eb2a82015-05-13 10:52:34 +05301109 memset(channel_status,0,24);
1110
1111 /* block start bit in preamble bit 3 */
1112 channel_status[0] |= PROFESSIONAL;
1113 //compre out
1114 channel_status[0] |= NON_LPCM;
1115 // sample rate; fixed 48K for default/transcode
1116 channel_status[3] |= SR_48000;
1117}
1118
1119#ifdef HDMI_PASSTHROUGH_ENABLED
1120int32_t get_compressed_channel_status(void *audio_stream_data,
1121 uint32_t audio_frame_size,
1122 unsigned char *channel_status,
1123 enum audio_parser_code_type codec_type)
1124 // codec_type - AUDIO_PARSER_CODEC_AC3
1125 // - AUDIO_PARSER_CODEC_DTS
1126{
1127 unsigned char *stream;
1128 int ret = 0;
1129 stream = (unsigned char *)audio_stream_data;
1130
1131 if (audio_stream_data == NULL || audio_frame_size == 0) {
1132 ALOGW("no buffer to get channel status, return default for compress");
1133 get_default_compressed_channel_status(channel_status);
1134 return ret;
1135 }
1136
1137 memset(channel_status,0,24);
1138 if(init_audio_parser(stream, audio_frame_size, codec_type) == -1)
1139 {
1140 ALOGE("init audio parser failed");
1141 return -1;
1142 }
1143 ret = get_channel_status(channel_status, codec_type);
1144 return ret;
1145
1146}
1147
1148#endif
1149
1150void get_lpcm_channel_status(uint32_t sampleRate,
1151 unsigned char *channel_status)
1152{
1153 int32_t status = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05301154 memset(channel_status,0,24);
1155 /* block start bit in preamble bit 3 */
1156 channel_status[0] |= PROFESSIONAL;
1157 //LPCM OUT
1158 channel_status[0] &= ~NON_LPCM;
1159
1160 switch (sampleRate) {
1161 case 8000:
1162 case 11025:
1163 case 12000:
1164 case 16000:
1165 case 22050:
1166 channel_status[3] |= SR_NOTID;
Preetam Singh Ranawat61716b12015-12-14 11:55:24 +05301167 break;
Ashish Jain81eb2a82015-05-13 10:52:34 +05301168 case 24000:
1169 channel_status[3] |= SR_24000;
1170 break;
1171 case 32000:
1172 channel_status[3] |= SR_32000;
1173 break;
1174 case 44100:
1175 channel_status[3] |= SR_44100;
1176 break;
1177 case 48000:
1178 channel_status[3] |= SR_48000;
1179 break;
1180 case 88200:
1181 channel_status[3] |= SR_88200;
1182 break;
1183 case 96000:
1184 channel_status[3] |= SR_96000;
1185 break;
1186 case 176400:
1187 channel_status[3] |= SR_176400;
1188 break;
1189 case 192000:
1190 channel_status[3] |= SR_192000;
1191 break;
1192 default:
1193 ALOGV("Invalid sample_rate %u\n", sampleRate);
1194 status = -1;
1195 break;
1196 }
1197}
1198
1199void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes)
1200{
1201 unsigned char channel_status[24]={0};
1202 struct snd_aes_iec958 iec958;
1203 const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
1204 struct mixer_ctl *ctl;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301205 ALOGV("%s: buffer %s bytes %zd", __func__, buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05301206#ifdef HDMI_PASSTHROUGH_ENABLED
1207 if (audio_extn_is_dolby_format(out->format) &&
1208 /*TODO:Extend code to support DTS passthrough*/
1209 /*set compressed channel status bits*/
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301210 audio_extn_passthru_is_passthrough_stream(out)){
Ashish Jain81eb2a82015-05-13 10:52:34 +05301211 get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
1212 } else
1213#endif
1214 {
1215 /*set channel status bit for LPCM*/
1216 get_lpcm_channel_status(out->sample_rate, channel_status);
1217 }
1218
1219 memcpy(iec958.status, channel_status,sizeof(iec958.status));
1220 ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_ctl_name);
1221 if (!ctl) {
1222 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1223 __func__, mixer_ctl_name);
1224 return;
1225 }
1226 if (mixer_ctl_set_array(ctl, &iec958, sizeof(iec958)) < 0) {
1227 ALOGE("%s: Could not set channel status for ext HDMI ",
1228 __func__);
1229 return;
1230 }
1231
1232}
1233#endif