blob: 9f78a0cf28d4b072d350964d4852b367ea19ea85 [file] [log] [blame]
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07001/*
Dhananjay Kumar14245982017-01-16 20:21:00 +05302 * Copyright (c) 2014-2017, 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
Manish Dewangan27346042017-03-01 12:56:12 +053023#include <inttypes.h>
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070024#include <errno.h>
25#include <cutils/properties.h>
26#include <cutils/config_utils.h>
27#include <stdlib.h>
28#include <dlfcn.h>
29#include <cutils/str_parms.h>
30#include <cutils/log.h>
31#include <cutils/misc.h>
32
Manish Dewangan07de2142017-02-27 19:27:20 +053033
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070034#include "audio_hw.h"
35#include "platform.h"
36#include "platform_api.h"
37#include "audio_extn.h"
Narsinga Rao Chella212e2542014-11-17 19:57:04 -080038#include "voice.h"
Manish Dewangan07de2142017-02-27 19:27:20 +053039#include <sound/compress_params.h>
40#include <sound/compress_offload.h>
41#include <tinycompress/tinycompress.h>
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053042
43#ifdef DYNAMIC_LOG_ENABLED
44#include <log_xml_parser.h>
45#define LOG_MASK HAL_MOD_FILE_UTILS
46#include <log_utils.h>
47#endif
48
Ashish Jain81eb2a82015-05-13 10:52:34 +053049#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
50#ifdef HDMI_PASSTHROUGH_ENABLED
51#include "audio_parsers.h"
52#endif
53#endif
54
Yamit Mehtaa0d653a2016-11-25 20:33:25 +053055#ifdef LINUX_ENABLED
56#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/etc/audio_output_policy.conf"
Dhananjay Kumard6d32152016-10-13 16:11:03 +053057#define AUDIO_IO_POLICY_VENDOR_CONFIG_FILE "/etc/audio_io_policy.conf"
Yamit Mehtaa0d653a2016-11-25 20:33:25 +053058#else
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070059#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
Dhananjay Kumard6d32152016-10-13 16:11:03 +053060#define AUDIO_IO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_io_policy.conf"
Yamit Mehtaa0d653a2016-11-25 20:33:25 +053061#endif
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070062
63#define OUTPUTS_TAG "outputs"
Dhananjay Kumard6d32152016-10-13 16:11:03 +053064#define INPUTS_TAG "inputs"
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070065
66#define DYNAMIC_VALUE_TAG "dynamic"
67#define FLAGS_TAG "flags"
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +053068#define PROFILES_TAG "profile"
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070069#define FORMATS_TAG "formats"
70#define SAMPLING_RATES_TAG "sampling_rates"
71#define BIT_WIDTH_TAG "bit_width"
72#define APP_TYPE_TAG "app_type"
73
74#define STRING_TO_ENUM(string) { #string, string }
75#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
76
Ben Rombergera04fabc2014-11-14 12:16:03 -080077#define BASE_TABLE_SIZE 64
78#define MAX_BASEINDEX_LEN 256
79
Ben Romberger1aaaf862017-04-06 17:49:46 -070080#ifndef SND_AUDIOCODEC_TRUEHD
81#define SND_AUDIOCODEC_TRUEHD 0x00000023
82#endif
83
Vikram Panduranga93f080e2017-06-07 18:16:14 -070084#define APP_TYPE_VOIP_AUDIO 0x1113A
85
Ashish Jain81eb2a82015-05-13 10:52:34 +053086#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
87#define PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
88#define NON_LPCM (1<<1) /* 0 = audio, 1 = non-audio */
89#define SR_44100 (0<<0) /* 44.1kHz */
90#define SR_NOTID (1<<0) /* non indicated */
91#define SR_48000 (2<<0) /* 48kHz */
92#define SR_32000 (3<<0) /* 32kHz */
93#define SR_22050 (4<<0) /* 22.05kHz */
94#define SR_24000 (6<<0) /* 24kHz */
95#define SR_88200 (8<<0) /* 88.2kHz */
96#define SR_96000 (10<<0) /* 96kHz */
97#define SR_176400 (12<<0) /* 176.4kHz */
98#define SR_192000 (14<<0) /* 192kHz */
99
100#endif
Manish Dewangan07de2142017-02-27 19:27:20 +0530101
102/* ToDo: Check and update a proper value in msec */
103#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
104
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700105struct string_to_enum {
106 const char *name;
107 uint32_t value;
108};
109
110const struct string_to_enum s_flag_name_to_enum_table[] = {
111 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
112 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
113 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -0800114 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700115 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
116 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
117 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -0700118 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700119#ifdef INCALL_MUSIC_ENABLED
120 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
121#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -0700122 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530123 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TIMESTAMP),
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700124 STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530125 STRING_TO_ENUM(AUDIO_INPUT_FLAG_NONE),
126 STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
127 STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
128 STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW),
129 STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC),
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530130 STRING_TO_ENUM(AUDIO_INPUT_FLAG_TIMESTAMP),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700131};
132
133const struct string_to_enum s_format_name_to_enum_table[] = {
Ashish Jain83a6cc22016-06-28 14:34:17 +0530134 STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700135 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
Ashish Jain5106d362016-05-11 19:23:33 +0530136 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
137 STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
Ashish Jainf1eaa582016-05-23 20:54:24 +0530138 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700139 STRING_TO_ENUM(AUDIO_FORMAT_MP3),
140 STRING_TO_ENUM(AUDIO_FORMAT_AAC),
141 STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
Mingming Yinae3530f2014-07-03 16:50:18 -0700142 STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
143 STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700144 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
Mingming Yinae3530f2014-07-03 16:50:18 -0700145 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700146 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530147 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700148 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700149 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937),
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530150#ifdef AUDIO_EXTN_FORMATS_ENABLED
151 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700152 STRING_TO_ENUM(AUDIO_FORMAT_WMA),
153 STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
154 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700155 STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
156 STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
157 STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
158 STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
159 STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
160 STRING_TO_ENUM(AUDIO_FORMAT_MP2),
161 STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
Amit Shekhar6f461b12014-08-01 14:52:58 -0700162 STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530163 STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
164 STRING_TO_ENUM(AUDIO_FORMAT_APE),
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -0700165 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Alexy Josephcd8eaed2014-12-11 12:46:53 -0800166 STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
167 STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
168 STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
Manish Dewangana6fc5442015-08-24 20:30:31 +0530169 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS),
Ashish Jaine513a872015-11-19 17:00:56 +0530170 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LC),
171 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1),
172 STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2),
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530173 STRING_TO_ENUM(AUDIO_FORMAT_DSD),
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530174 STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM),
175 STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM_LC),
176 STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V1),
177 STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V2),
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530178 STRING_TO_ENUM(AUDIO_FORMAT_APTX),
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700179#endif
180};
181
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530182/* payload structure avt_device drift query */
183struct audio_avt_device_drift_stats {
184 uint32_t minor_version;
185 /* Indicates the device interface direction as either
186 * source (Tx) or sink (Rx).
187 */
188 uint16_t device_direction;
189 /*params exposed to client */
190 struct audio_avt_device_drift_param drift_param;
191};
192
Ben Rombergera04fabc2014-11-14 12:16:03 -0800193static char bTable[BASE_TABLE_SIZE] = {
194 'A','B','C','D','E','F','G','H','I','J','K','L',
195 'M','N','O','P','Q','R','S','T','U','V','W','X',
196 'Y','Z','a','b','c','d','e','f','g','h','i','j',
197 'k','l','m','n','o','p','q','r','s','t','u','v',
198 'w','x','y','z','0','1','2','3','4','5','6','7',
199 '8','9','+','/'
200};
201
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700202static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
203 const char *name)
204{
205 size_t i;
206 for (i = 0; i < size; i++) {
207 if (strcmp(table[i].name, name) == 0) {
208 ALOGV("%s found %s", __func__, table[i].name);
209 return table[i].value;
210 }
211 }
212 return 0;
213}
214
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530215static audio_io_flags_t parse_flag_names(char *name)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700216{
217 uint32_t flag = 0;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530218 audio_io_flags_t io_flags;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800219 char *last_r;
220 char *flag_name = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700221 while (flag_name != NULL) {
222 if (strlen(flag_name) != 0) {
223 flag |= string_to_enum(s_flag_name_to_enum_table,
224 ARRAY_SIZE(s_flag_name_to_enum_table),
225 flag_name);
226 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800227 flag_name = strtok_r(NULL, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700228 }
229
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -0800230 ALOGV("parse_flag_names: flag - %x", flag);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530231 io_flags.in_flags = (audio_input_flags_t)flag;
232 io_flags.out_flags = (audio_output_flags_t)flag;
233 return io_flags;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700234}
235
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530236static void parse_format_names(char *name, struct streams_io_cfg *s_info)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700237{
238 struct stream_format *sf_info = NULL;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800239 char *last_r;
240 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700241
242 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
243 return;
244
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530245 list_init(&s_info->format_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700246 while (str != NULL) {
247 audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
248 ARRAY_SIZE(s_format_name_to_enum_table), str);
249 ALOGV("%s: format - %d", __func__, format);
250 if (format != 0) {
251 sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700252 if (sf_info == NULL)
253 break; /* return whatever was parsed */
254
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700255 sf_info->format = format;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530256 list_add_tail(&s_info->format_list, &sf_info->list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700257 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800258 str = strtok_r(NULL, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700259 }
260}
261
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530262static void parse_sample_rate_names(char *name, struct streams_io_cfg *s_info)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700263{
Amit Shekhar6f461b12014-08-01 14:52:58 -0700264 struct stream_sample_rate *ss_info = NULL;
265 uint32_t sample_rate = 48000;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800266 char *last_r;
267 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700268
Amit Shekhar6f461b12014-08-01 14:52:58 -0700269 if (str != NULL && 0 == strcmp(str, DYNAMIC_VALUE_TAG))
270 return;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700271
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530272 list_init(&s_info->sample_rate_list);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700273 while (str != NULL) {
274 sample_rate = (uint32_t)strtol(str, (char **)NULL, 10);
275 ALOGV("%s: sample_rate - %d", __func__, sample_rate);
276 if (0 != sample_rate) {
277 ss_info = (struct stream_sample_rate *)calloc(1, sizeof(struct stream_sample_rate));
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800278 if (!ss_info) {
279 ALOGE("%s: memory allocation failure", __func__);
280 return;
281 }
Amit Shekhar6f461b12014-08-01 14:52:58 -0700282 ss_info->sample_rate = sample_rate;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530283 list_add_tail(&s_info->sample_rate_list, &ss_info->list);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700284 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800285 str = strtok_r(NULL, "|", &last_r);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700286 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700287}
288
289static int parse_bit_width_names(char *name)
290{
291 int bit_width = 16;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800292 char *last_r;
293 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700294
295 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
296 bit_width = (int)strtol(str, (char **)NULL, 10);
297
298 ALOGV("%s: bit_width - %d", __func__, bit_width);
299 return bit_width;
300}
301
302static int parse_app_type_names(void *platform, char *name)
303{
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700304 int app_type = platform_get_default_app_type(platform);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800305 char *last_r;
306 char *str = strtok_r(name, "|", &last_r);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700307
308 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
309 app_type = (int)strtol(str, (char **)NULL, 10);
310
311 ALOGV("%s: app_type - %d", __func__, app_type);
312 return app_type;
313}
314
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530315static void update_streams_cfg_list(cnode *root, void *platform,
316 struct listnode *streams_cfg_list)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700317{
318 cnode *node = root->first_child;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530319 struct streams_io_cfg *s_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700320
321 ALOGV("%s", __func__);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530322 s_info = (struct streams_io_cfg *)calloc(1, sizeof(struct streams_io_cfg));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700323
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530324 if (!s_info) {
325 ALOGE("failed to allocate mem for s_info list element");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700326 return;
327 }
328
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700329 while (node) {
330 if (strcmp(node->name, FLAGS_TAG) == 0) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530331 s_info->flags = parse_flag_names((char *)node->value);
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530332 } else if (strcmp(node->name, PROFILES_TAG) == 0) {
333 strlcpy(s_info->profile, (char *)node->value, sizeof(s_info->profile));
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700334 } else if (strcmp(node->name, FORMATS_TAG) == 0) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530335 parse_format_names((char *)node->value, s_info);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700336 } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530337 s_info->app_type_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
338 parse_sample_rate_names((char *)node->value, s_info);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700339 } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530340 s_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700341 } else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530342 s_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700343 }
344 node = node->next;
345 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530346 list_add_tail(streams_cfg_list, &s_info->list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700347}
348
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530349static void load_cfg_list(cnode *root, void *platform,
350 struct listnode *streams_output_cfg_list,
351 struct listnode *streams_input_cfg_list)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700352{
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530353 cnode *node = NULL;
354
355 node = config_find(root, OUTPUTS_TAG);
356 if (node != NULL) {
357 node = node->first_child;
358 while (node) {
359 ALOGV("%s: loading output %s", __func__, node->name);
360 update_streams_cfg_list(node, platform, streams_output_cfg_list);
361 node = node->next;
362 }
363 } else {
364 ALOGI("%s: could not load output, node is NULL", __func__);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700365 }
366
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530367 node = config_find(root, INPUTS_TAG);
368 if (node != NULL) {
369 node = node->first_child;
370 while (node) {
371 ALOGV("%s: loading input %s", __func__, node->name);
372 update_streams_cfg_list(node, platform, streams_input_cfg_list);
373 node = node->next;
374 }
375 } else {
376 ALOGI("%s: could not load input, node is NULL", __func__);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700377 }
378}
379
380static void send_app_type_cfg(void *platform, struct mixer *mixer,
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530381 struct listnode *streams_output_cfg_list,
382 struct listnode *streams_input_cfg_list)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700383{
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530384 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700385 int length = 0, i, num_app_types = 0;
386 struct listnode *node;
387 bool update;
388 struct mixer_ctl *ctl = NULL;
389 const char *mixer_ctl_name = "App Type Config";
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530390 struct streams_io_cfg *s_info = NULL;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700391
392 if (!mixer) {
393 ALOGE("%s: mixer is null",__func__);
394 return;
395 }
396 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
397 if (!ctl) {
398 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
399 return;
400 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530401 app_type_cfg[length++] = num_app_types;
402
403 if (list_empty(streams_output_cfg_list)) {
404 app_type_cfg[length++] = platform_get_default_app_type_v2(platform, PCM_PLAYBACK);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700405 app_type_cfg[length++] = 48000;
406 app_type_cfg[length++] = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530407 num_app_types += 1;
408 }
409 if (list_empty(streams_input_cfg_list)) {
410 app_type_cfg[length++] = platform_get_default_app_type_v2(platform, PCM_CAPTURE);
411 app_type_cfg[length++] = 48000;
412 app_type_cfg[length++] = 16;
413 num_app_types += 1;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700414 }
415
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700416 list_for_each(node, streams_output_cfg_list) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530417 s_info = node_to_item(node, struct streams_io_cfg, list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700418 update = true;
419 for (i=0; i<length; i=i+3) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530420 if (app_type_cfg[i+1] == 0)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700421 break;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530422 else if (app_type_cfg[i+1] == (size_t)s_info->app_type_cfg.app_type) {
Dhananjay Kumar9cc498b2016-12-20 21:04:13 +0530423 if (app_type_cfg[i+2] < (size_t)s_info->app_type_cfg.sample_rate)
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530424 app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
Dhananjay Kumar9cc498b2016-12-20 21:04:13 +0530425 if (app_type_cfg[i+3] < (size_t)s_info->app_type_cfg.bit_width)
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530426 app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700427 update = false;
428 break;
429 }
430 }
431 if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530432 num_app_types += 1;
433 app_type_cfg[length++] = s_info->app_type_cfg.app_type;
434 app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
435 app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
436 }
437 }
438 list_for_each(node, streams_input_cfg_list) {
439 s_info = node_to_item(node, struct streams_io_cfg, list);
440 update = true;
441 for (i=0; i<length; i=i+3) {
442 if (app_type_cfg[i+1] == 0)
443 break;
444 else if (app_type_cfg[i+1] == (size_t)s_info->app_type_cfg.app_type) {
Dhananjay Kumar9cc498b2016-12-20 21:04:13 +0530445 if (app_type_cfg[i+2] < (size_t)s_info->app_type_cfg.sample_rate)
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530446 app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
Dhananjay Kumar9cc498b2016-12-20 21:04:13 +0530447 if (app_type_cfg[i+3] < (size_t)s_info->app_type_cfg.bit_width)
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530448 app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
449 update = false;
450 break;
451 }
452 }
453 if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
454 num_app_types += 1;
455 app_type_cfg[length++] = s_info->app_type_cfg.app_type;
456 app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
457 app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700458 }
459 }
460 ALOGV("%s: num_app_types: %d", __func__, num_app_types);
461 if (num_app_types) {
462 app_type_cfg[0] = num_app_types;
463 mixer_ctl_set_array(ctl, app_type_cfg, length);
464 }
465}
466
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530467void audio_extn_utils_update_streams_cfg_lists(void *platform,
468 struct mixer *mixer,
469 struct listnode *streams_output_cfg_list,
470 struct listnode *streams_input_cfg_list)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700471{
472 cnode *root;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530473 char *data = NULL;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700474
475 ALOGV("%s", __func__);
476 list_init(streams_output_cfg_list);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530477 list_init(streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700478
479 root = config_node("", "");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700480 if (root == NULL) {
481 ALOGE("cfg_list, NULL config root");
482 return;
483 }
484
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530485 data = (char *)load_file(AUDIO_IO_POLICY_VENDOR_CONFIG_FILE, NULL);
486 if (data == NULL) {
487 ALOGD("%s: failed to open io config file(%s), trying older config file",
488 __func__, AUDIO_IO_POLICY_VENDOR_CONFIG_FILE);
489 data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
490 if (data == NULL) {
491 send_app_type_cfg(platform, mixer,
492 streams_output_cfg_list,
493 streams_input_cfg_list);
494 ALOGE("%s: could not load io policy config!", __func__);
yidongh6eb4f752017-04-19 18:20:57 +0800495 free(root);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530496 return;
497 }
498 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700499
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530500 config_load(root, data);
501 load_cfg_list(root, platform, streams_output_cfg_list,
502 streams_input_cfg_list);
503
504 send_app_type_cfg(platform, mixer, streams_output_cfg_list,
505 streams_input_cfg_list);
Alexy Josephaee4fdd2016-01-29 13:02:07 -0800506
507 config_free(root);
yidongh6eb4f752017-04-19 18:20:57 +0800508 free(root);
Alexy Josephaee4fdd2016-01-29 13:02:07 -0800509 free(data);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700510}
511
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530512static void audio_extn_utils_dump_streams_cfg_list(
513 struct listnode *streams_cfg_list)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700514{
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700515 struct listnode *node_i, *node_j;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530516 struct streams_io_cfg *s_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700517 struct stream_format *sf_info;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700518 struct stream_sample_rate *ss_info;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530519
520 list_for_each(node_i, streams_cfg_list) {
521 s_info = node_to_item(node_i, struct streams_io_cfg, list);
522 ALOGV("%s: flags-%d, sample_rate-%d, bit_width-%d, app_type-%d",
523 __func__, s_info->flags.out_flags, s_info->app_type_cfg.sample_rate,
524 s_info->app_type_cfg.bit_width, s_info->app_type_cfg.app_type);
525 list_for_each(node_j, &s_info->format_list) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700526 sf_info = node_to_item(node_j, struct stream_format, list);
527 ALOGV("format-%x", sf_info->format);
528 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530529 list_for_each(node_j, &s_info->sample_rate_list) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700530 ss_info = node_to_item(node_j, struct stream_sample_rate, list);
531 ALOGV("sample rate-%d", ss_info->sample_rate);
532 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700533 }
534}
535
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530536void audio_extn_utils_dump_streams_cfg_lists(
537 struct listnode *streams_output_cfg_list,
538 struct listnode *streams_input_cfg_list)
539{
540 ALOGV("%s", __func__);
541 audio_extn_utils_dump_streams_cfg_list(streams_output_cfg_list);
542 audio_extn_utils_dump_streams_cfg_list(streams_input_cfg_list);
543}
544
545static void audio_extn_utils_release_streams_cfg_list(
546 struct listnode *streams_cfg_list)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700547{
548 struct listnode *node_i, *node_j;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530549 struct streams_io_cfg *s_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700550
551 ALOGV("%s", __func__);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530552
553 while (!list_empty(streams_cfg_list)) {
554 node_i = list_head(streams_cfg_list);
555 s_info = node_to_item(node_i, struct streams_io_cfg, list);
556 while (!list_empty(&s_info->format_list)) {
557 node_j = list_head(&s_info->format_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700558 list_remove(node_j);
559 free(node_to_item(node_j, struct stream_format, list));
560 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530561 while (!list_empty(&s_info->sample_rate_list)) {
562 node_j = list_head(&s_info->sample_rate_list);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700563 list_remove(node_j);
564 free(node_to_item(node_j, struct stream_sample_rate, list));
565 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700566 list_remove(node_i);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530567 free(node_to_item(node_i, struct streams_io_cfg, list));
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700568 }
569}
570
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530571void audio_extn_utils_release_streams_cfg_lists(
572 struct listnode *streams_output_cfg_list,
573 struct listnode *streams_input_cfg_list)
574{
575 ALOGV("%s", __func__);
576 audio_extn_utils_release_streams_cfg_list(streams_output_cfg_list);
577 audio_extn_utils_release_streams_cfg_list(streams_input_cfg_list);
578}
579
580static bool set_app_type_cfg(struct streams_io_cfg *s_info,
581 struct stream_app_type_cfg *app_type_cfg,
582 uint32_t sample_rate, uint32_t bit_width)
Amit Shekhar6f461b12014-08-01 14:52:58 -0700583 {
584 struct listnode *node_i;
585 struct stream_sample_rate *ss_info;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530586 list_for_each(node_i, &s_info->sample_rate_list) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700587 ss_info = node_to_item(node_i, struct stream_sample_rate, list);
588 if ((sample_rate <= ss_info->sample_rate) &&
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530589 (bit_width == s_info->app_type_cfg.bit_width)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -0700590
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530591 app_type_cfg->app_type = s_info->app_type_cfg.app_type;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700592 app_type_cfg->sample_rate = ss_info->sample_rate;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530593 app_type_cfg->bit_width = s_info->app_type_cfg.bit_width;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700594 ALOGV("%s app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
595 __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
596 return true;
597 }
598 }
599 /*
600 * Reiterate through the list assuming dafault sample rate.
601 * Handles scenario where input sample rate is higher
602 * than all sample rates in list for the input bit width.
603 */
604 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800605
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530606 list_for_each(node_i, &s_info->sample_rate_list) {
Amit Shekhar6f461b12014-08-01 14:52:58 -0700607 ss_info = node_to_item(node_i, struct stream_sample_rate, list);
608 if ((sample_rate <= ss_info->sample_rate) &&
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530609 (bit_width == s_info->app_type_cfg.bit_width)) {
610 app_type_cfg->app_type = s_info->app_type_cfg.app_type;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700611 app_type_cfg->sample_rate = sample_rate;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530612 app_type_cfg->bit_width = s_info->app_type_cfg.bit_width;
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800613 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 -0700614 __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
615 return true;
616 }
617 }
618 return false;
619}
620
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530621void audio_extn_utils_update_stream_input_app_type_cfg(void *platform,
622 struct listnode *streams_input_cfg_list,
623 audio_devices_t devices __unused,
624 audio_input_flags_t flags,
625 audio_format_t format,
626 uint32_t sample_rate,
627 uint32_t bit_width,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530628 char* profile,
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530629 struct stream_app_type_cfg *app_type_cfg)
630{
631 struct listnode *node_i, *node_j;
632 struct streams_io_cfg *s_info;
633 struct stream_format *sf_info;
634
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530635 ALOGV("%s: flags: 0x%x, format: 0x%x sample_rate %d, profile %s",
636 __func__, flags, format, sample_rate, profile);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530637
638 list_for_each(node_i, streams_input_cfg_list) {
639 s_info = node_to_item(node_i, struct streams_io_cfg, list);
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530640 /* Along with flags do profile matching if set at either end.*/
641 if (s_info->flags.in_flags == flags &&
642 ((profile[0] == '\0' && s_info->profile[0] == '\0') ||
643 strncmp(s_info->profile, profile, sizeof(s_info->profile)) == 0)) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530644 list_for_each(node_j, &s_info->format_list) {
645 sf_info = node_to_item(node_j, struct stream_format, list);
646 if (sf_info->format == format) {
647 if (set_app_type_cfg(s_info, app_type_cfg, sample_rate, bit_width))
648 return;
649 }
650 }
651 }
652 }
653 ALOGW("%s: App type could not be selected. Falling back to default", __func__);
654 app_type_cfg->app_type = platform_get_default_app_type_v2(platform, PCM_CAPTURE);
655 app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
656 app_type_cfg->bit_width = 16;
657}
658
659void audio_extn_utils_update_stream_output_app_type_cfg(void *platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700660 struct listnode *streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700661 audio_devices_t devices,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700662 audio_output_flags_t flags,
663 audio_format_t format,
Amit Shekhar6f461b12014-08-01 14:52:58 -0700664 uint32_t sample_rate,
665 uint32_t bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +0530666 audio_channel_mask_t channel_mask,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530667 char *profile,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700668 struct stream_app_type_cfg *app_type_cfg)
669{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530670 struct listnode *node_i, *node_j;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530671 struct streams_io_cfg *s_info;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700672 struct stream_format *sf_info;
Manish Dewangan837dc462015-05-27 10:17:41 +0530673 char value[PROPERTY_VALUE_MAX] = {0};
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700674
Ashish Jain058165c2016-09-28 23:18:48 +0530675 if ((bit_width >= 24) &&
Amit Shekhar1d896042014-10-03 13:16:09 -0700676 (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
Amit Shekhar5a39c912014-10-14 15:39:30 -0700677 int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
678 if (-ENOSYS != bw)
679 bit_width = (uint32_t)bw;
Amit Shekhar1d896042014-10-03 13:16:09 -0700680 sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
681 ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
682 }
683
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700684 property_get("vendor.audio.playback.mch.downsample",value,"");
Manish Dewangan837dc462015-05-27 10:17:41 +0530685 if (!strncmp("true", value, sizeof("true"))) {
686 if ((popcount(channel_mask) > 2) &&
687 (sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
688 !(flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)) {
689 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
690 ALOGD("%s: MCH session defaulting sample rate to %d",
691 __func__, sample_rate);
692 }
693 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530694
695 /* Set sampling rate to 176.4 for DSD64
696 * and 352.8Khz for DSD128.
697 * Set Bit Width to 16. output will be 16 bit
698 * post DoP in ASM.
699 */
700 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH) &&
701 (format == AUDIO_FORMAT_DSD)) {
702 bit_width = 16;
703 if (sample_rate == INPUT_SAMPLING_RATE_DSD64)
704 sample_rate = OUTPUT_SAMPLING_RATE_DSD64;
705 else if (sample_rate == INPUT_SAMPLING_RATE_DSD128)
706 sample_rate = OUTPUT_SAMPLING_RATE_DSD128;
707 }
708
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530709 if(devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
710 //TODO: Handle fractional sampling rate configuration for LL
711 audio_extn_a2dp_get_apptype_params(&sample_rate, &bit_width);
712 ALOGI("%s using %d sampling rate %d bit width for A2DP CoPP",
713 __func__, sample_rate, bit_width);
714 }
715
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -0800716 ALOGV("%s: flags: %x, format: %x sample_rate %d, profile %s, app_type %d",
717 __func__, flags, format, sample_rate, profile, app_type_cfg->app_type);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700718 list_for_each(node_i, streams_output_cfg_list) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530719 s_info = node_to_item(node_i, struct streams_io_cfg, list);
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530720 /* Along with flags do profile matching if set at either end.*/
721 if (s_info->flags.out_flags == flags &&
722 ((profile[0] == '\0' && s_info->profile[0] == '\0') ||
723 strncmp(s_info->profile, profile, sizeof(s_info->profile)) == 0)) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530724 list_for_each(node_j, &s_info->format_list) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700725 sf_info = node_to_item(node_j, struct stream_format, list);
726 if (sf_info->format == format) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530727 if (set_app_type_cfg(s_info, app_type_cfg, sample_rate, bit_width))
Amit Shekhar6f461b12014-08-01 14:52:58 -0700728 return;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700729 }
730 }
731 }
732 }
733 list_for_each(node_i, streams_output_cfg_list) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530734 s_info = node_to_item(node_i, struct streams_io_cfg, list);
735 if (s_info->flags.out_flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700736 ALOGV("Compatible output profile not found.");
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530737 app_type_cfg->app_type = s_info->app_type_cfg.app_type;
738 app_type_cfg->sample_rate = s_info->app_type_cfg.sample_rate;
739 app_type_cfg->bit_width = s_info->app_type_cfg.bit_width;
Amit Shekhar6f461b12014-08-01 14:52:58 -0700740 ALOGV("%s Default to primary output: App type: %d sample_rate %d",
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530741 __func__, s_info->app_type_cfg.app_type, app_type_cfg->sample_rate);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700742 return;
743 }
744 }
745 ALOGW("%s: App type could not be selected. Falling back to default", __func__);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700746 app_type_cfg->app_type = platform_get_default_app_type(platform);
Amit Shekhar6f461b12014-08-01 14:52:58 -0700747 app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700748 app_type_cfg->bit_width = 16;
749}
750
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530751static bool audio_is_this_native_usecase(struct audio_usecase *uc)
752{
753 bool native_usecase = false;
754 struct stream_out *out = (struct stream_out*) uc->stream.out;
755
756 if (PCM_PLAYBACK == uc->type && out != NULL &&
757 NATIVE_AUDIO_MODE_INVALID != platform_get_native_support() &&
758 is_offload_usecase(uc->id) &&
759 (out->sample_rate == OUTPUT_SAMPLING_RATE_44100))
760 native_usecase = true;
761
762 return native_usecase;
763}
764
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -0800765
766static inline bool audio_is_vr_mode_on(struct audio_device *(__attribute__((unused)) adev))
767{
768 return adev->vr_audio_mode_enabled;
769}
770
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530771void audio_extn_utils_update_stream_app_type_cfg_for_usecase(
772 struct audio_device *adev,
773 struct audio_usecase *usecase)
774{
775 ALOGV("%s", __func__);
776
777 switch(usecase->type) {
778 case PCM_PLAYBACK:
779 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
780 &adev->streams_output_cfg_list,
781 usecase->stream.out->devices,
782 usecase->stream.out->flags,
783 usecase->stream.out->format,
784 usecase->stream.out->sample_rate,
785 usecase->stream.out->bit_width,
786 usecase->stream.out->channel_mask,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530787 usecase->stream.out->profile,
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530788 &usecase->stream.out->app_type_cfg);
789 ALOGV("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
790 break;
791 case PCM_CAPTURE:
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700792 if (usecase->id == USECASE_AUDIO_RECORD_VOIP)
793 usecase->stream.in->app_type_cfg.app_type = APP_TYPE_VOIP_AUDIO;
794 else
795 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530796 &adev->streams_input_cfg_list,
797 usecase->stream.in->device,
798 usecase->stream.in->flags,
799 usecase->stream.in->format,
800 usecase->stream.in->sample_rate,
801 usecase->stream.in->bit_width,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +0530802 usecase->stream.in->profile,
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530803 &usecase->stream.in->app_type_cfg);
804 ALOGV("%s Selected apptype: %d", __func__, usecase->stream.in->app_type_cfg.app_type);
805 break;
806 default:
807 ALOGE("%s: app type cfg not supported for usecase type (%d)",
808 __func__, usecase->type);
809 }
810}
811
Siena Richard7c2db772016-12-21 11:32:34 -0800812static int send_app_type_cfg_for_device(struct audio_device *adev,
813 struct audio_usecase *usecase,
814 int split_snd_device)
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700815{
816 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530817 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
818 int len = 0, rc;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700819 struct mixer_ctl *ctl;
Siena Richard7c2db772016-12-21 11:32:34 -0800820 int pcm_device_id = 0, acdb_dev_id, app_type;
821 int snd_device = split_snd_device, snd_device_be_idx = -1;
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530822 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Manish Dewangan837dc462015-05-27 10:17:41 +0530823 char value[PROPERTY_VALUE_MAX] = {0};
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700824
Siena Richard7c2db772016-12-21 11:32:34 -0800825 ALOGV("%s: usecase->out_snd_device %s, usecase->in_snd_device %s, split_snd_device %s",
826 __func__, platform_get_snd_device_name(usecase->out_snd_device),
827 platform_get_snd_device_name(usecase->in_snd_device),
828 platform_get_snd_device_name(split_snd_device));
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700829
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530830 if (usecase->type != PCM_PLAYBACK && usecase->type != PCM_CAPTURE) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530831 ALOGE("%s: not a playback/capture path, no need to cfg app type", __func__);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700832 rc = 0;
833 goto exit_send_app_type_cfg;
834 }
835 if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
836 (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
837 (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -0800838 (usecase->id != USECASE_AUDIO_PLAYBACK_ULL) &&
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700839 (usecase->id != USECASE_AUDIO_PLAYBACK_VOIP) &&
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530840 (!is_offload_usecase(usecase->id)) &&
841 (usecase->type != PCM_CAPTURE)) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530842 ALOGV("%s: a rx/tx/loopback path where app type cfg is not required %d", __func__, usecase->id);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700843 rc = 0;
844 goto exit_send_app_type_cfg;
845 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -0800846
847 //if VR is active then only send the mixer control
848 if (usecase->id == USECASE_AUDIO_PLAYBACK_ULL && !audio_is_vr_mode_on(adev)) {
849 ALOGI("ULL doesnt need sending app type cfg, returning");
850 rc = 0;
851 goto exit_send_app_type_cfg;
852 }
853
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530854 if (usecase->type == PCM_PLAYBACK) {
Ben Romberger1fafdde2015-09-09 19:43:15 -0700855 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530856 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
857 "Audio Stream %d App Type Cfg", pcm_device_id);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700858 } else if (usecase->type == PCM_CAPTURE) {
Ben Romberger1fafdde2015-09-09 19:43:15 -0700859 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530860 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
861 "Audio Stream Capture %d App Type Cfg", pcm_device_id);
Srikanth Uyyala9d551402015-08-25 16:03:42 +0530862 }
Siena Richard7c2db772016-12-21 11:32:34 -0800863
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700864 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
865 if (!ctl) {
866 ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
867 mixer_ctl_name);
868 rc = -EINVAL;
869 goto exit_send_app_type_cfg;
870 }
Aditya Bavanari701a6992017-03-30 19:17:16 +0530871 snd_device = platform_get_spkr_prot_snd_device(snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530872
Rohit Kumar1181b292017-01-31 18:07:17 +0530873 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
874 if (acdb_dev_id <= 0) {
875 ALOGE("%s: Couldn't get the acdb dev id", __func__);
876 rc = -EINVAL;
877 goto exit_send_app_type_cfg;
878 }
879
Siena Richard7c2db772016-12-21 11:32:34 -0800880 snd_device_be_idx = platform_get_snd_device_backend_index(snd_device);
881 if (snd_device_be_idx < 0) {
882 ALOGE("%s: Couldn't get the backend index for snd device %s ret=%d",
883 __func__, platform_get_snd_device_name(snd_device),
884 snd_device_be_idx);
885 }
886
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530887 if ((usecase->type == PCM_PLAYBACK) && (usecase->stream.out != NULL)) {
Manish Dewangan837dc462015-05-27 10:17:41 +0530888
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700889 property_get("vendor.audio.playback.mch.downsample",value,"");
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530890 if (!strncmp("true", value, sizeof("true"))) {
891 if ((popcount(usecase->stream.out->channel_mask) > 2) &&
892 (usecase->stream.out->app_type_cfg.sample_rate > CODEC_BACKEND_DEFAULT_SAMPLE_RATE) &&
893 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
894 sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
895 }
Ashish Jainc02430d2016-01-04 10:42:43 +0530896
Ashish Jain4826f6c2017-02-06 13:33:20 +0530897 if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Mingming Yin21854652016-04-13 11:54:02 -0700898 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ashish Jaina052e572016-11-07 16:41:07 +0530899 } else if ((snd_device == SND_DEVICE_OUT_HDMI ||
900 snd_device == SND_DEVICE_OUT_USB_HEADSET ||
901 snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
902 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
903 /*
904 * To best utlize DSP, check if the stream sample rate is supported/multiple of
905 * configured device sample rate, if not update the COPP rate to be equal to the
906 * device sample rate, else open COPP at stream sample rate
907 */
908 platform_check_and_update_copp_sample_rate(adev->platform, snd_device,
909 usecase->stream.out->sample_rate,
910 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +0530911 } else if (((snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
912 !audio_is_this_native_usecase(usecase)) &&
Mingming Yin21854652016-04-13 11:54:02 -0700913 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
914 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Ashish Jain4826f6c2017-02-06 13:33:20 +0530915 /* Reset to default if no native stream is active*/
Mingming Yin21854652016-04-13 11:54:02 -0700916 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
917 }
918 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
919
Siena Richard7c2db772016-12-21 11:32:34 -0800920 app_type = usecase->stream.out->app_type_cfg.app_type;
921 app_type_cfg[len++] = app_type;
Mingming Yin21854652016-04-13 11:54:02 -0700922 app_type_cfg[len++] = acdb_dev_id;
923 if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700924 (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC) ||
925 (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD))
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530926 && audio_extn_passthru_is_passthrough_stream(usecase->stream.out)) {
Naresh Tanniru3a406772017-05-10 13:09:05 -0700927
928 sample_rate = sample_rate * 4;
929 if (sample_rate > HDMI_PASSTHROUGH_MAX_SAMPLE_RATE)
930 sample_rate = HDMI_PASSTHROUGH_MAX_SAMPLE_RATE;
Mingming Yin21854652016-04-13 11:54:02 -0700931 }
Naresh Tanniru3a406772017-05-10 13:09:05 -0700932 app_type_cfg[len++] = sample_rate;
933
Siena Richard7c2db772016-12-21 11:32:34 -0800934 if (snd_device_be_idx > 0)
935 app_type_cfg[len++] = snd_device_be_idx;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530936
Siena Richard7c2db772016-12-21 11:32:34 -0800937 ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d, snd_device_be_idx %d",
938 __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530939
940 } else if ((usecase->type == PCM_CAPTURE) && (usecase->stream.in != NULL)) {
Siena Richard7c2db772016-12-21 11:32:34 -0800941 app_type = usecase->stream.in->app_type_cfg.app_type;
942 app_type_cfg[len++] = app_type;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530943 app_type_cfg[len++] = acdb_dev_id;
Siena Richard7c2db772016-12-21 11:32:34 -0800944 sample_rate = usecase->stream.in->app_type_cfg.sample_rate;
945 app_type_cfg[len++] = sample_rate;
946 if (snd_device_be_idx > 0)
947 app_type_cfg[len++] = snd_device_be_idx;
948 ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d, snd_device_be_idx %d",
949 __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530950 } else {
Siena Richard7c2db772016-12-21 11:32:34 -0800951 app_type = platform_get_default_app_type_v2(adev->platform, usecase->type);
952 app_type_cfg[len++] = app_type;
Dhananjay Kumard6d32152016-10-13 16:11:03 +0530953 app_type_cfg[len++] = acdb_dev_id;
954 app_type_cfg[len++] = sample_rate;
Siena Richard7c2db772016-12-21 11:32:34 -0800955 if (snd_device_be_idx > 0)
956 app_type_cfg[len++] = snd_device_be_idx;
957 ALOGI("%s default app_type %d, acdb_dev_id %d, sample_rate %d, snd_device_be_idx %d",
958 __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
Ashish Jainc02430d2016-01-04 10:42:43 +0530959 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530960
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700961 mixer_ctl_set_array(ctl, app_type_cfg, len);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700962 rc = 0;
963exit_send_app_type_cfg:
964 return rc;
965}
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700966
Siena Richard7c2db772016-12-21 11:32:34 -0800967int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
968 struct audio_usecase *usecase)
969{
970 int i, num_devices = 0;
971 snd_device_t new_snd_devices[SND_DEVICE_OUT_END] = {0};
972 int rc = 0;
973
974 switch (usecase->type) {
975 case PCM_PLAYBACK:
976 ALOGD("%s: usecase->out_snd_device %s",
977 __func__, platform_get_snd_device_name(usecase->out_snd_device));
978 /* check for out combo device */
979 if (platform_split_snd_device(adev->platform,
980 usecase->out_snd_device,
981 &num_devices, new_snd_devices)) {
982 new_snd_devices[0] = usecase->out_snd_device;
983 num_devices = 1;
984 }
985 break;
986 case PCM_CAPTURE:
987 ALOGD("%s: usecase->in_snd_device %s",
988 __func__, platform_get_snd_device_name(usecase->in_snd_device));
989 /* check for in combo device */
990 if (platform_split_snd_device(adev->platform,
991 usecase->in_snd_device,
992 &num_devices, new_snd_devices)) {
993 new_snd_devices[0] = usecase->in_snd_device;
994 num_devices = 1;
995 }
996 break;
997 default:
998 ALOGI("%s: not a playback/capture path, no need to cfg app type", __func__);
999 rc = 0;
1000 break;
1001 }
1002
1003 for (i = 0; i < num_devices; i++) {
1004 rc = send_app_type_cfg_for_device(adev, usecase, new_snd_devices[i]);
1005 if (rc)
1006 break;
1007 }
1008
1009 return rc;
1010}
1011
Preetam Singh Ranawat9519e9c2015-11-18 16:05:55 +05301012int read_line_from_file(const char *path, char *buf, size_t count)
1013{
1014 char * fgets_ret;
1015 FILE * fd;
1016 int rv;
1017
1018 fd = fopen(path, "r");
1019 if (fd == NULL)
1020 return -1;
1021
1022 fgets_ret = fgets(buf, (int)count, fd);
1023 if (NULL != fgets_ret) {
1024 rv = (int)strlen(buf);
1025 } else {
1026 rv = ferror(fd);
1027 }
1028 fclose(fd);
1029
1030 return rv;
1031}
1032
Ashish Jainf1eaa582016-05-23 20:54:24 +05301033/*Translates ALSA formats to AOSP PCM formats*/
1034audio_format_t alsa_format_to_hal(uint32_t alsa_format)
1035{
1036 audio_format_t format;
1037
1038 switch(alsa_format) {
1039 case SNDRV_PCM_FORMAT_S16_LE:
1040 format = AUDIO_FORMAT_PCM_16_BIT;
1041 break;
1042 case SNDRV_PCM_FORMAT_S24_3LE:
1043 format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1044 break;
1045 case SNDRV_PCM_FORMAT_S24_LE:
1046 format = AUDIO_FORMAT_PCM_8_24_BIT;
1047 break;
1048 case SNDRV_PCM_FORMAT_S32_LE:
1049 format = AUDIO_FORMAT_PCM_32_BIT;
1050 break;
1051 default:
1052 ALOGW("Incorrect ALSA format");
1053 format = AUDIO_FORMAT_INVALID;
1054 }
1055 return format;
1056}
1057
1058/*Translates hal format (AOSP) to alsa formats*/
1059uint32_t hal_format_to_alsa(audio_format_t hal_format)
1060{
1061 uint32_t alsa_format;
1062
1063 switch (hal_format) {
1064 case AUDIO_FORMAT_PCM_32_BIT: {
1065 if (platform_supports_true_32bit())
1066 alsa_format = SNDRV_PCM_FORMAT_S32_LE;
1067 else
1068 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
1069 }
1070 break;
1071 case AUDIO_FORMAT_PCM_8_BIT:
1072 alsa_format = SNDRV_PCM_FORMAT_S8;
1073 break;
1074 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
1075 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
1076 break;
1077 case AUDIO_FORMAT_PCM_8_24_BIT: {
1078 if (platform_supports_true_32bit())
1079 alsa_format = SNDRV_PCM_FORMAT_S32_LE;
1080 else
1081 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
1082 }
1083 break;
1084 case AUDIO_FORMAT_PCM_FLOAT:
1085 alsa_format = SNDRV_PCM_FORMAT_S24_3LE;
1086 break;
1087 default:
1088 case AUDIO_FORMAT_PCM_16_BIT:
1089 alsa_format = SNDRV_PCM_FORMAT_S16_LE;
1090 break;
1091 }
1092 return alsa_format;
1093}
1094
Ashish Jain83a6cc22016-06-28 14:34:17 +05301095/*Translates PCM formats to AOSP formats*/
1096audio_format_t pcm_format_to_hal(uint32_t pcm_format)
1097{
1098 audio_format_t format = AUDIO_FORMAT_INVALID;
1099
1100 switch(pcm_format) {
1101 case PCM_FORMAT_S16_LE:
1102 format = AUDIO_FORMAT_PCM_16_BIT;
1103 break;
1104 case PCM_FORMAT_S24_3LE:
1105 format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1106 break;
1107 case PCM_FORMAT_S24_LE:
1108 format = AUDIO_FORMAT_PCM_8_24_BIT;
1109 break;
1110 case PCM_FORMAT_S32_LE:
1111 format = AUDIO_FORMAT_PCM_32_BIT;
1112 break;
1113 default:
1114 ALOGW("Incorrect PCM format");
1115 format = AUDIO_FORMAT_INVALID;
1116 }
1117 return format;
1118}
1119
1120/*Translates hal format (AOSP) to alsa formats*/
1121uint32_t hal_format_to_pcm(audio_format_t hal_format)
1122{
1123 uint32_t pcm_format;
1124
1125 switch (hal_format) {
1126 case AUDIO_FORMAT_PCM_32_BIT:
1127 case AUDIO_FORMAT_PCM_8_24_BIT:
1128 case AUDIO_FORMAT_PCM_FLOAT: {
1129 if (platform_supports_true_32bit())
1130 pcm_format = PCM_FORMAT_S32_LE;
1131 else
1132 pcm_format = PCM_FORMAT_S24_3LE;
1133 }
1134 break;
1135 case AUDIO_FORMAT_PCM_8_BIT:
1136 pcm_format = PCM_FORMAT_S8;
1137 break;
1138 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
1139 pcm_format = PCM_FORMAT_S24_3LE;
1140 break;
1141 default:
1142 case AUDIO_FORMAT_PCM_16_BIT:
1143 pcm_format = PCM_FORMAT_S16_LE;
1144 break;
1145 }
1146 return pcm_format;
1147}
1148
Ashish Jainf1eaa582016-05-23 20:54:24 +05301149uint32_t get_alsa_fragment_size(uint32_t bytes_per_sample,
1150 uint32_t sample_rate,
1151 uint32_t noOfChannels)
1152{
1153 uint32_t fragment_size = 0;
1154 uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
1155
1156 fragment_size = (pcm_offload_time
1157 * sample_rate
1158 * bytes_per_sample
1159 * noOfChannels)/1000;
1160 if (fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
1161 fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
1162 else if (fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
1163 fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
1164 /*To have same PCM samples for all channels, the buffer size requires to
1165 *be multiple of (number of channels * bytes per sample)
1166 *For writes to succeed, the buffer must be written at address which is multiple of 32
1167 */
1168 fragment_size = ALIGN(fragment_size, (bytes_per_sample * noOfChannels * 32));
1169
1170 ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
1171 return fragment_size;
1172}
1173
1174/* Calculates the fragment size required to configure compress session.
1175 * Based on the alsa format selected, decide if conversion is needed in
1176
1177 * HAL ( e.g. convert AUDIO_FORMAT_PCM_FLOAT input format to
1178 * AUDIO_FORMAT_PCM_24_BIT_PACKED before writing to the compress driver.
1179 */
1180void audio_extn_utils_update_direct_pcm_fragment_size(struct stream_out *out)
1181{
Ashish Jain83a6cc22016-06-28 14:34:17 +05301182 audio_format_t dst_format = out->hal_op_format;
1183 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05301184 uint32_t hal_op_bytes_per_sample = audio_bytes_per_sample(dst_format);
1185 uint32_t hal_ip_bytes_per_sample = audio_bytes_per_sample(src_format);
1186
1187 out->compr_config.fragment_size =
1188 get_alsa_fragment_size(hal_op_bytes_per_sample,
1189 out->sample_rate,
1190 popcount(out->channel_mask));
1191
1192 if ((src_format != dst_format) &&
1193 hal_op_bytes_per_sample != hal_ip_bytes_per_sample) {
1194
Ashish Jain83a6cc22016-06-28 14:34:17 +05301195 out->hal_fragment_size =
Ashish Jainf1eaa582016-05-23 20:54:24 +05301196 ((out->compr_config.fragment_size * hal_ip_bytes_per_sample) /
1197 hal_op_bytes_per_sample);
1198 ALOGI("enable conversion hal_input_fragment_size is %d src_format %x dst_format %x",
Ashish Jain83a6cc22016-06-28 14:34:17 +05301199 out->hal_fragment_size, src_format, dst_format);
Ashish Jainf1eaa582016-05-23 20:54:24 +05301200 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05301201 out->hal_fragment_size = out->compr_config.fragment_size;
Ashish Jainf1eaa582016-05-23 20:54:24 +05301202 }
1203}
1204
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301205/* converts pcm format 24_8 to 8_24 inplace */
1206size_t audio_extn_utils_convert_format_24_8_to_8_24(void *buf, size_t bytes)
1207{
1208 size_t i = 0;
1209 int *int_buf_stream = buf;
1210
1211 if ((bytes % 4) != 0) {
1212 ALOGE("%s: wrong inout buffer! ... is not 32 bit aligned ", __func__);
1213 return -EINVAL;
1214 }
1215
1216 for (; i < (bytes / 4); i++)
1217 int_buf_stream[i] >>= 8;
1218
1219 return bytes;
1220}
1221
1222int get_snd_codec_id(audio_format_t format)
1223{
1224 int id = 0;
1225
1226 switch (format & AUDIO_FORMAT_MAIN_MASK) {
1227 case AUDIO_FORMAT_MP3:
1228 id = SND_AUDIOCODEC_MP3;
1229 break;
1230 case AUDIO_FORMAT_AAC:
1231 id = SND_AUDIOCODEC_AAC;
1232 break;
1233 case AUDIO_FORMAT_AAC_ADTS:
1234 id = SND_AUDIOCODEC_AAC;
1235 break;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05301236 case AUDIO_FORMAT_AAC_LATM:
1237 id = SND_AUDIOCODEC_AAC;
1238 break;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301239 case AUDIO_FORMAT_PCM:
1240 id = SND_AUDIOCODEC_PCM;
1241 break;
1242 case AUDIO_FORMAT_FLAC:
1243 id = SND_AUDIOCODEC_FLAC;
1244 break;
1245 case AUDIO_FORMAT_ALAC:
1246 id = SND_AUDIOCODEC_ALAC;
1247 break;
1248 case AUDIO_FORMAT_APE:
1249 id = SND_AUDIOCODEC_APE;
1250 break;
1251 case AUDIO_FORMAT_VORBIS:
1252 id = SND_AUDIOCODEC_VORBIS;
1253 break;
1254 case AUDIO_FORMAT_WMA:
1255 id = SND_AUDIOCODEC_WMA;
1256 break;
1257 case AUDIO_FORMAT_WMA_PRO:
1258 id = SND_AUDIOCODEC_WMA_PRO;
1259 break;
Satish Babu Patakokila0c313922016-12-08 12:07:08 +05301260 case AUDIO_FORMAT_MP2:
1261 id = SND_AUDIOCODEC_MP2;
1262 break;
Satish Babu Patakokila915ecba2017-01-10 17:43:56 +05301263 case AUDIO_FORMAT_AC3:
1264 id = SND_AUDIOCODEC_AC3;
1265 break;
1266 case AUDIO_FORMAT_E_AC3:
1267 case AUDIO_FORMAT_E_AC3_JOC:
1268 id = SND_AUDIOCODEC_EAC3;
1269 break;
1270 case AUDIO_FORMAT_DTS:
1271 case AUDIO_FORMAT_DTS_HD:
1272 id = SND_AUDIOCODEC_DTS;
1273 break;
Ben Romberger1aaaf862017-04-06 17:49:46 -07001274 case AUDIO_FORMAT_DOLBY_TRUEHD:
1275 id = SND_AUDIOCODEC_TRUEHD;
1276 break;
Naresh Tanniru928f0862017-04-07 16:44:23 -07001277 case AUDIO_FORMAT_IEC61937:
1278 id = SND_AUDIOCODEC_IEC61937;
1279 break;
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05301280 case AUDIO_FORMAT_DSD:
1281 id = SND_AUDIOCODEC_DSD;
1282 break;
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301283 case AUDIO_FORMAT_APTX:
1284 id = SND_AUDIOCODEC_APTX;
1285 break;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301286 default:
1287 ALOGE("%s: Unsupported audio format :%x", __func__, format);
1288 }
1289
1290 return id;
1291}
1292
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001293void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
1294 struct audio_usecase *usecase)
1295{
1296 int type = usecase->type;
1297
Dhananjay Kumar14245982017-01-16 20:21:00 +05301298 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001299 struct stream_out *out = usecase->stream.out;
1300 int snd_device = usecase->out_snd_device;
1301 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001302 platform_get_spkr_prot_snd_device(snd_device) : snd_device;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301303 platform_send_audio_calibration(adev->platform, usecase,
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001304 out->app_type_cfg.app_type,
Preetam Singh Ranawat61716b12015-12-14 11:55:24 +05301305 usecase->stream.out->app_type_cfg.sample_rate);
Dhananjay Kumar14245982017-01-16 20:21:00 +05301306 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301307 platform_send_audio_calibration(adev->platform, usecase,
1308 usecase->stream.in->app_type_cfg.app_type,
1309 usecase->stream.in->app_type_cfg.sample_rate);
Vidyakumar Athota653aaef2017-03-16 11:11:31 -07001310 } else if (type == PCM_HFP_CALL || type == PCM_CAPTURE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301311 /* when app type is default. the sample rate is not used to send cal */
1312 platform_send_audio_calibration(adev->platform, usecase,
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301313 platform_get_default_app_type_v2(adev->platform, usecase->type),
1314 48000);
Vidyakumar Athotae57f6002017-03-01 13:13:16 -08001315 } else {
1316 /* No need to send audio calibration for voice and voip call usecases */
1317 if ((type != VOICE_CALL) && (type != VOIP_CALL))
1318 ALOGW("%s: No audio calibration for usecase type = %d", __func__, type);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001319 }
1320}
1321
Ben Rombergera04fabc2014-11-14 12:16:03 -08001322// Base64 Encode and Decode
1323// Not all features supported. This must be used only with following conditions.
1324// Decode Modes: Support with and without padding
1325// CRLF not handling. So no CRLF in string to decode.
1326// Encode Modes: Supports only padding
1327int b64decode(char *inp, int ilen, uint8_t* outp)
1328{
1329 int i, j, k, ii, num;
1330 int rem, pcnt;
1331 uint32_t res=0;
1332 uint8_t getIndex[MAX_BASEINDEX_LEN];
1333 uint8_t tmp, cflag;
1334
1335 if(inp == NULL || outp == NULL || ilen <= 0) {
1336 ALOGE("[%s] received NULL pointer or zero length",__func__);
1337 return -1;
1338 }
1339
1340 memset(getIndex, MAX_BASEINDEX_LEN-1, sizeof(getIndex));
1341 for(i=0;i<BASE_TABLE_SIZE;i++) {
1342 getIndex[(uint8_t)bTable[i]] = (uint8_t)i;
1343 }
1344 getIndex[(uint8_t)'=']=0;
1345
1346 j=0;k=0;
1347 num = ilen/4;
1348 rem = ilen%4;
1349 if(rem==0)
1350 num = num-1;
1351 cflag=0;
1352 for(i=0; i<num; i++) {
1353 res=0;
1354 for(ii=0;ii<4;ii++) {
1355 res = res << 6;
1356 tmp = getIndex[(uint8_t)inp[j++]];
1357 res = res | tmp;
1358 cflag = cflag | tmp;
1359 }
1360 outp[k++] = (res >> 16)&0xFF;
1361 outp[k++] = (res >> 8)&0xFF;
1362 outp[k++] = res & 0xFF;
1363 }
1364
1365 // Handle last bytes special
1366 pcnt=0;
1367 if(rem == 0) {
1368 //With padding or full data
1369 res = 0;
1370 for(ii=0;ii<4;ii++) {
1371 if(inp[j] == '=')
1372 pcnt++;
1373 res = res << 6;
1374 tmp = getIndex[(uint8_t)inp[j++]];
1375 res = res | tmp;
1376 cflag = cflag | tmp;
1377 }
1378 outp[k++] = res >> 16;
1379 if(pcnt == 2)
1380 goto done;
1381 outp[k++] = (res>>8)&0xFF;
1382 if(pcnt == 1)
1383 goto done;
1384 outp[k++] = res&0xFF;
1385 } else {
1386 //without padding
1387 res = 0;
1388 for(i=0;i<rem;i++) {
1389 res = res << 6;
1390 tmp = getIndex[(uint8_t)inp[j++]];
1391 res = res | tmp;
1392 cflag = cflag | tmp;
1393 }
1394 for(i=rem;i<4;i++) {
1395 res = res << 6;
1396 pcnt++;
1397 }
1398 outp[k++] = res >> 16;
1399 if(pcnt == 2)
1400 goto done;
1401 outp[k++] = (res>>8)&0xFF;
1402 if(pcnt == 1)
1403 goto done;
1404 outp[k++] = res&0xFF;
1405 }
1406done:
1407 if(cflag == 0xFF) {
1408 ALOGE("[%s] base64 decode failed. Invalid character found %s",
1409 __func__, inp);
1410 return 0;
1411 }
1412 return k;
1413}
1414
1415int b64encode(uint8_t *inp, int ilen, char* outp)
1416{
1417 int i,j,k, num;
1418 int rem=0;
1419 uint32_t res=0;
1420
1421 if(inp == NULL || outp == NULL || ilen<=0) {
1422 ALOGE("[%s] received NULL pointer or zero input length",__func__);
1423 return -1;
1424 }
1425
1426 num = ilen/3;
1427 rem = ilen%3;
1428 j=0;k=0;
1429 for(i=0; i<num; i++) {
1430 //prepare index
1431 res = inp[j++]<<16;
1432 res = res | inp[j++]<<8;
1433 res = res | inp[j++];
1434 //get output map from index
1435 outp[k++] = (char) bTable[(res>>18)&0x3F];
1436 outp[k++] = (char) bTable[(res>>12)&0x3F];
1437 outp[k++] = (char) bTable[(res>>6)&0x3F];
1438 outp[k++] = (char) bTable[res&0x3F];
1439 }
1440
1441 switch(rem) {
1442 case 1:
1443 res = inp[j++]<<16;
1444 outp[k++] = (char) bTable[res>>18];
1445 outp[k++] = (char) bTable[(res>>12)&0x3F];
1446 //outp[k++] = '=';
1447 //outp[k++] = '=';
1448 break;
1449 case 2:
1450 res = inp[j++]<<16;
1451 res = res | inp[j++]<<8;
1452 outp[k++] = (char) bTable[res>>18];
1453 outp[k++] = (char) bTable[(res>>12)&0x3F];
1454 outp[k++] = (char) bTable[(res>>6)&0x3F];
1455 //outp[k++] = '=';
1456 break;
1457 default:
1458 break;
1459 }
Ben Rombergera04fabc2014-11-14 12:16:03 -08001460 outp[k] = '\0';
1461 return k;
1462}
Ashish Jain81eb2a82015-05-13 10:52:34 +05301463
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301464
1465int audio_extn_utils_get_codec_version(const char *snd_card_name,
1466 int card_num,
1467 char *codec_version)
1468{
1469 char procfs_path[50];
1470 FILE *fp;
1471
1472 if (strstr(snd_card_name, "tasha")) {
1473 snprintf(procfs_path, sizeof(procfs_path),
1474 "/proc/asound/card%d/codecs/tasha/version", card_num);
1475 if ((fp = fopen(procfs_path, "r")) != NULL) {
1476 fgets(codec_version, CODEC_VERSION_MAX_LENGTH, fp);
1477 fclose(fp);
1478 } else {
1479 ALOGE("%s: ERROR. cannot open %s", __func__, procfs_path);
1480 return -ENOENT;
1481 }
1482 ALOGD("%s: codec version %s", __func__, codec_version);
1483 }
1484
1485 return 0;
1486}
1487
1488
Ashish Jain81eb2a82015-05-13 10:52:34 +05301489#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
1490
1491void get_default_compressed_channel_status(
1492 unsigned char *channel_status)
1493{
Ashish Jain81eb2a82015-05-13 10:52:34 +05301494 memset(channel_status,0,24);
1495
1496 /* block start bit in preamble bit 3 */
1497 channel_status[0] |= PROFESSIONAL;
1498 //compre out
1499 channel_status[0] |= NON_LPCM;
1500 // sample rate; fixed 48K for default/transcode
1501 channel_status[3] |= SR_48000;
1502}
1503
1504#ifdef HDMI_PASSTHROUGH_ENABLED
1505int32_t get_compressed_channel_status(void *audio_stream_data,
1506 uint32_t audio_frame_size,
1507 unsigned char *channel_status,
1508 enum audio_parser_code_type codec_type)
1509 // codec_type - AUDIO_PARSER_CODEC_AC3
1510 // - AUDIO_PARSER_CODEC_DTS
1511{
1512 unsigned char *stream;
1513 int ret = 0;
1514 stream = (unsigned char *)audio_stream_data;
1515
1516 if (audio_stream_data == NULL || audio_frame_size == 0) {
1517 ALOGW("no buffer to get channel status, return default for compress");
1518 get_default_compressed_channel_status(channel_status);
1519 return ret;
1520 }
1521
1522 memset(channel_status,0,24);
1523 if(init_audio_parser(stream, audio_frame_size, codec_type) == -1)
1524 {
1525 ALOGE("init audio parser failed");
1526 return -1;
1527 }
1528 ret = get_channel_status(channel_status, codec_type);
1529 return ret;
1530
1531}
1532
1533#endif
1534
1535void get_lpcm_channel_status(uint32_t sampleRate,
1536 unsigned char *channel_status)
1537{
1538 int32_t status = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05301539 memset(channel_status,0,24);
1540 /* block start bit in preamble bit 3 */
1541 channel_status[0] |= PROFESSIONAL;
1542 //LPCM OUT
1543 channel_status[0] &= ~NON_LPCM;
1544
1545 switch (sampleRate) {
1546 case 8000:
1547 case 11025:
1548 case 12000:
1549 case 16000:
1550 case 22050:
1551 channel_status[3] |= SR_NOTID;
Preetam Singh Ranawat61716b12015-12-14 11:55:24 +05301552 break;
Ashish Jain81eb2a82015-05-13 10:52:34 +05301553 case 24000:
1554 channel_status[3] |= SR_24000;
1555 break;
1556 case 32000:
1557 channel_status[3] |= SR_32000;
1558 break;
1559 case 44100:
1560 channel_status[3] |= SR_44100;
1561 break;
1562 case 48000:
1563 channel_status[3] |= SR_48000;
1564 break;
1565 case 88200:
1566 channel_status[3] |= SR_88200;
1567 break;
1568 case 96000:
1569 channel_status[3] |= SR_96000;
1570 break;
1571 case 176400:
1572 channel_status[3] |= SR_176400;
1573 break;
1574 case 192000:
1575 channel_status[3] |= SR_192000;
1576 break;
1577 default:
1578 ALOGV("Invalid sample_rate %u\n", sampleRate);
1579 status = -1;
1580 break;
1581 }
1582}
1583
1584void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes)
1585{
1586 unsigned char channel_status[24]={0};
1587 struct snd_aes_iec958 iec958;
1588 const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
1589 struct mixer_ctl *ctl;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301590 ALOGV("%s: buffer %s bytes %zd", __func__, buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05301591#ifdef HDMI_PASSTHROUGH_ENABLED
1592 if (audio_extn_is_dolby_format(out->format) &&
1593 /*TODO:Extend code to support DTS passthrough*/
1594 /*set compressed channel status bits*/
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301595 audio_extn_passthru_is_passthrough_stream(out)){
Ashish Jain81eb2a82015-05-13 10:52:34 +05301596 get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
1597 } else
1598#endif
1599 {
1600 /*set channel status bit for LPCM*/
1601 get_lpcm_channel_status(out->sample_rate, channel_status);
1602 }
1603
1604 memcpy(iec958.status, channel_status,sizeof(iec958.status));
1605 ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_ctl_name);
1606 if (!ctl) {
1607 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1608 __func__, mixer_ctl_name);
1609 return;
1610 }
1611 if (mixer_ctl_set_array(ctl, &iec958, sizeof(iec958)) < 0) {
1612 ALOGE("%s: Could not set channel status for ext HDMI ",
1613 __func__);
1614 return;
1615 }
1616
1617}
1618#endif
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301619
1620int audio_extn_utils_get_avt_device_drift(
1621 struct audio_usecase *usecase,
1622 struct audio_avt_device_drift_param *drift_param)
1623{
1624 int ret = 0, count = 0;
1625 char avt_device_drift_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
Naresh Tanniru6160c712017-04-17 15:43:48 +05301626 const char *backend = NULL;
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301627 struct mixer_ctl *ctl = NULL;
1628 struct audio_avt_device_drift_stats drift_stats;
1629 struct audio_device *adev = NULL;
1630
1631 if (usecase != NULL && usecase->type == PCM_PLAYBACK) {
Naresh Tanniru6160c712017-04-17 15:43:48 +05301632 backend = platform_get_snd_device_backend_interface(usecase->out_snd_device);
1633 if (!backend) {
1634 ALOGE("%s: Unsupported device %d", __func__,
1635 usecase->stream.out->devices);
1636 ret = -EINVAL;
1637 goto done;
1638 }
1639 strlcpy(avt_device_drift_mixer_ctl_name,
1640 backend,
1641 MIXER_PATH_MAX_LENGTH);
1642
1643 count = strlen(backend);
1644 if (MIXER_PATH_MAX_LENGTH - count > 0) {
1645 strlcat(&avt_device_drift_mixer_ctl_name[count],
1646 " DRIFT",
1647 MIXER_PATH_MAX_LENGTH - count);
1648 } else {
1649 ret = -EINVAL;
1650 goto done;
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301651 }
1652 } else {
Naresh Tanniru7586e292017-04-13 10:38:13 +05301653 ALOGE("%s: Invalid usecase",__func__);
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301654 ret = -EINVAL;
Naresh Tanniru6160c712017-04-17 15:43:48 +05301655 goto done;
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301656 }
1657
Naresh Tanniru6160c712017-04-17 15:43:48 +05301658 adev = usecase->stream.out->dev;
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301659 ctl = mixer_get_ctl_by_name(adev->mixer, avt_device_drift_mixer_ctl_name);
1660 if (!ctl) {
1661 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1662 __func__, avt_device_drift_mixer_ctl_name);
1663
1664 ret = -EINVAL;
1665 goto done;
1666 }
1667
1668 ALOGV("%s: Getting AV Timer vs Device Drift mixer ctrl name %s", __func__,
1669 avt_device_drift_mixer_ctl_name);
1670
1671 mixer_ctl_update(ctl);
1672 count = mixer_ctl_get_num_values(ctl);
1673 if (count != sizeof(struct audio_avt_device_drift_stats)) {
1674 ALOGE("%s: mixer_ctl_get_num_values() invalid drift_stats data size",
1675 __func__);
1676
1677 ret = -EINVAL;
1678 goto done;
1679 }
1680
1681 ret = mixer_ctl_get_array(ctl, (void *)&drift_stats, count);
1682 if (ret != 0) {
1683 ALOGE("%s: mixer_ctl_get_array() failed to get drift_stats Params",
1684 __func__);
1685
1686 ret = -EINVAL;
1687 goto done;
1688 }
1689 memcpy(drift_param, &drift_stats.drift_param,
1690 sizeof(struct audio_avt_device_drift_param));
1691done:
1692 return ret;
1693}
Manish Dewangan07de2142017-02-27 19:27:20 +05301694
1695#ifdef SNDRV_COMPRESS_PATH_DELAY
1696int audio_extn_utils_compress_get_dsp_latency(struct stream_out *out)
1697{
1698 int ret = -EINVAL;
1699 struct snd_compr_metadata metadata;
1700 int delay_ms = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1701
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001702 if (property_get_bool("vendor.audio.playback.dsp.pathdelay", false)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05301703 ALOGD("%s:: Quering DSP delay %d",__func__, __LINE__);
1704 if (!(is_offload_usecase(out->usecase))) {
1705 ALOGE("%s:: not supported for non offload session", __func__);
1706 goto exit;
1707 }
1708
1709 if (!out->compr) {
1710 ALOGD("%s:: Invalid compress handle,returning default dsp latency",
1711 __func__);
1712 goto exit;
1713 }
1714
1715 metadata.key = SNDRV_COMPRESS_PATH_DELAY;
1716 ret = compress_get_metadata(out->compr, &metadata);
1717 if(ret) {
1718 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
1719 goto exit;
1720 }
1721 delay_ms = metadata.value[0] / 1000; /*convert to ms*/
1722 } else {
1723 ALOGD("%s:: Using Fix DSP delay",__func__);
1724 }
1725
1726exit:
1727 ALOGD("%s:: delay in ms is %d",__func__, delay_ms);
1728 return delay_ms;
1729}
1730#else
1731int audio_extn_utils_compress_get_dsp_latency(struct stream_out *out __unused)
1732{
1733 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1734}
1735#endif
Manish Dewangan69426c82017-01-30 17:35:36 +05301736
1737#ifdef SNDRV_COMPRESS_RENDER_MODE
1738int audio_extn_utils_compress_set_render_mode(struct stream_out *out)
1739{
1740 struct snd_compr_metadata metadata;
1741 int ret = -EINVAL;
1742
1743 if (!(is_offload_usecase(out->usecase))) {
1744 ALOGE("%s:: not supported for non offload session", __func__);
1745 goto exit;
1746 }
1747
1748 if (!out->compr) {
1749 ALOGD("%s:: Invalid compress handle",
1750 __func__);
1751 goto exit;
1752 }
1753
1754 ALOGD("%s:: render mode %d", __func__, out->render_mode);
1755
1756 metadata.key = SNDRV_COMPRESS_RENDER_MODE;
1757 if (out->render_mode == RENDER_MODE_AUDIO_MASTER) {
1758 metadata.value[0] = SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER;
1759 } else if (out->render_mode == RENDER_MODE_AUDIO_STC_MASTER) {
1760 metadata.value[0] = SNDRV_COMPRESS_RENDER_MODE_STC_MASTER;
1761 } else {
1762 ret = 0;
1763 goto exit;
1764 }
1765 ret = compress_set_metadata(out->compr, &metadata);
1766 if(ret) {
1767 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
1768 }
1769exit:
1770 return ret;
1771}
1772#else
1773int audio_extn_utils_compress_set_render_mode(struct stream_out *out __unused)
1774{
1775 ALOGD("%s:: configuring render mode not supported", __func__);
1776 return 0;
1777}
1778#endif
Manish Dewangan58229382017-02-02 15:48:41 +05301779
1780#ifdef SNDRV_COMPRESS_CLK_REC_MODE
1781int audio_extn_utils_compress_set_clk_rec_mode(
1782 struct audio_usecase *usecase)
1783{
1784 struct snd_compr_metadata metadata;
1785 struct stream_out *out = NULL;
1786 int ret = -EINVAL;
1787
Naresh Tanniru7586e292017-04-13 10:38:13 +05301788 if (usecase == NULL || usecase->type != PCM_PLAYBACK) {
Manish Dewangan58229382017-02-02 15:48:41 +05301789 ALOGE("%s:: Invalid use case", __func__);
1790 goto exit;
1791 }
1792
1793 out = usecase->stream.out;
1794 if (!out) {
1795 ALOGE("%s:: invalid stream", __func__);
1796 goto exit;
1797 }
1798
1799 if (!is_offload_usecase(out->usecase)) {
1800 ALOGE("%s:: not supported for non offload session", __func__);
1801 goto exit;
1802 }
1803
1804 if (out->render_mode != RENDER_MODE_AUDIO_STC_MASTER) {
1805 ALOGD("%s:: clk recovery is only supported in STC render mode",
1806 __func__);
1807 ret = 0;
1808 goto exit;
1809 }
1810
1811 if (!out->compr) {
1812 ALOGD("%s:: Invalid compress handle",
1813 __func__);
1814 goto exit;
1815 }
1816 metadata.key = SNDRV_COMPRESS_CLK_REC_MODE;
1817 switch(usecase->out_snd_device) {
1818 case SND_DEVICE_OUT_HDMI:
1819 case SND_DEVICE_OUT_SPEAKER_AND_HDMI:
1820 case SND_DEVICE_OUT_DISPLAY_PORT:
1821 case SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT:
1822 metadata.value[0] = SNDRV_COMPRESS_CLK_REC_MODE_NONE;
1823 break;
1824 default:
1825 metadata.value[0] = SNDRV_COMPRESS_CLK_REC_MODE_AUTO;
1826 break;
1827 }
1828
1829 ALOGD("%s:: clk recovery mode %d",__func__, metadata.value[0]);
1830
1831 ret = compress_set_metadata(out->compr, &metadata);
1832 if(ret) {
1833 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
1834 }
1835
1836exit:
1837 return ret;
1838}
1839#else
1840int audio_extn_utils_compress_set_clk_rec_mode(
1841 struct audio_usecase *usecase __unused)
1842{
1843 ALOGD("%s:: configuring render mode not supported", __func__);
1844 return 0;
1845}
1846#endif
Manish Dewangan27346042017-03-01 12:56:12 +05301847
1848#ifdef SNDRV_COMPRESS_RENDER_WINDOW
1849int audio_extn_utils_compress_set_render_window(
1850 struct stream_out *out,
1851 struct audio_out_render_window_param *render_window)
1852{
1853 struct snd_compr_metadata metadata;
1854 int ret = -EINVAL;
1855
Manish Dewangan27346042017-03-01 12:56:12 +05301856 if(render_window == NULL) {
1857 ALOGE("%s:: Invalid render_window", __func__);
1858 goto exit;
1859 }
1860
Aniket Kumar Lata1e1d3662017-06-01 18:45:48 -07001861 ALOGD("%s:: render window start 0x%"PRIx64" end 0x%"PRIx64"",
1862 __func__,render_window->render_ws, render_window->render_we);
1863
Manish Dewangan27346042017-03-01 12:56:12 +05301864 if (!is_offload_usecase(out->usecase)) {
1865 ALOGE("%s:: not supported for non offload session", __func__);
1866 goto exit;
1867 }
1868
Naresh Tanniru6160c712017-04-17 15:43:48 +05301869 if ((out->render_mode != RENDER_MODE_AUDIO_MASTER) &&
1870 (out->render_mode != RENDER_MODE_AUDIO_STC_MASTER)) {
Manish Dewangan27346042017-03-01 12:56:12 +05301871 ALOGD("%s:: only supported in timestamp mode, current "
1872 "render mode mode %d", __func__, out->render_mode);
1873 goto exit;
1874 }
1875
1876 if (!out->compr) {
1877 ALOGW("%s:: offload session not yet opened,"
1878 "render window will be configure later", __func__);
1879 /* store render window to reconfigure in start_output_stream() */
1880 goto exit;
1881 }
1882
1883 metadata.key = SNDRV_COMPRESS_RENDER_WINDOW;
1884 /*render window start value */
1885 metadata.value[0] = 0xFFFFFFFF & render_window->render_ws; /* lsb */
1886 metadata.value[1] = \
1887 (0xFFFFFFFF00000000 & render_window->render_ws) >> 32; /* msb*/
1888 /*render window end value */
1889 metadata.value[2] = 0xFFFFFFFF & render_window->render_we; /* lsb */
1890 metadata.value[3] = \
1891 (0xFFFFFFFF00000000 & render_window->render_we) >> 32; /* msb*/
1892
1893 ret = compress_set_metadata(out->compr, &metadata);
1894 if(ret) {
1895 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
1896 }
1897
1898exit:
1899 return ret;
1900}
1901#else
1902int audio_extn_utils_compress_set_render_window(
1903 struct stream_out *out __unused,
1904 struct audio_out_render_window_param *render_window __unused)
1905{
1906 ALOGD("%s:: configuring render window not supported", __func__);
1907 return 0;
1908}
1909#endif
Manish Dewangan14956cc2017-02-14 18:54:42 +05301910
1911#ifdef SNDRV_COMPRESS_START_DELAY
1912int audio_extn_utils_compress_set_start_delay(
1913 struct stream_out *out,
1914 struct audio_out_start_delay_param *delay_param)
1915{
1916 struct snd_compr_metadata metadata;
1917 int ret = -EINVAL;
1918
1919 if(delay_param == NULL) {
1920 ALOGE("%s:: Invalid delay_param", __func__);
1921 goto exit;
1922 }
1923
1924 ALOGD("%s:: render start delay 0x%"PRIx64" ", __func__,
1925 delay_param->start_delay);
1926
1927 if (!is_offload_usecase(out->usecase)) {
1928 ALOGE("%s:: not supported for non offload session", __func__);
1929 goto exit;
1930 }
1931
Naresh Tanniru6160c712017-04-17 15:43:48 +05301932 if ((out->render_mode != RENDER_MODE_AUDIO_MASTER) &&
1933 (out->render_mode != RENDER_MODE_AUDIO_STC_MASTER)) {
Manish Dewangan14956cc2017-02-14 18:54:42 +05301934 ALOGD("%s:: only supported in timestamp mode, current "
1935 "render mode mode %d", __func__, out->render_mode);
1936 goto exit;
1937 }
1938
1939 if (!out->compr) {
1940 ALOGW("%s:: offload session not yet opened,"
1941 "start delay will be configure later", __func__);
1942 goto exit;
1943 }
1944
1945 metadata.key = SNDRV_COMPRESS_START_DELAY;
1946 metadata.value[0] = 0xFFFFFFFF & delay_param->start_delay; /* lsb */
1947 metadata.value[1] = \
1948 (0xFFFFFFFF00000000 & delay_param->start_delay) >> 32; /* msb*/
1949
1950 ret = compress_set_metadata(out->compr, &metadata);
1951 if(ret) {
1952 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
1953 }
1954
1955exit:
1956 return ret;
1957}
1958#else
1959int audio_extn_utils_compress_set_start_delay(
1960 struct stream_out *out __unused,
1961 struct audio_out_start_delay_param *delay_param __unused)
1962{
1963 ALOGD("%s:: configuring render window not supported", __func__);
1964 return 0;
1965}
1966#endif
Vignesh Kulothungan55396882017-04-20 14:37:02 -07001967
1968#define MAX_SND_CARD 8
1969#define RETRY_US 500000
1970#define RETRY_NUMBER 10
1971
1972int audio_extn_utils_get_snd_card_num()
1973{
1974
1975 void *hw_info = NULL;
1976 struct mixer *mixer = NULL;
1977 int retry_num = 0;
1978 int snd_card_num = 0;
1979 char* snd_card_name = NULL;
1980
1981 while (snd_card_num < MAX_SND_CARD) {
1982 mixer = mixer_open(snd_card_num);
1983
1984 while (!mixer && retry_num < RETRY_NUMBER) {
1985 usleep(RETRY_US);
1986 mixer = mixer_open(snd_card_num);
1987 retry_num++;
1988 }
1989
1990 if (!mixer) {
1991 ALOGE("%s: Unable to open the mixer card: %d", __func__,
1992 snd_card_num);
1993 retry_num = 0;
1994 snd_card_num++;
1995 continue;
1996 }
1997
1998 snd_card_name = strdup(mixer_get_name(mixer));
1999 if (!snd_card_name) {
2000 ALOGE("failed to allocate memory for snd_card_name\n");
2001 mixer_close(mixer);
2002 return -1;
2003 }
2004 ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
2005
2006 hw_info = hw_info_init(snd_card_name);
2007 if (hw_info) {
2008 ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
2009 break;
2010 }
2011 ALOGE("%s: Failed to init hardware info", __func__);
2012 retry_num = 0;
2013 snd_card_num++;
Vignesh Kulothungan55396882017-04-20 14:37:02 -07002014
Dhananjay Kumara7e27832017-07-11 15:40:39 +05302015 free(snd_card_name);
2016 snd_card_name = NULL;
2017
2018 mixer_close(mixer);
2019 mixer = NULL;
2020 }
Vignesh Kulothungan55396882017-04-20 14:37:02 -07002021 if (snd_card_name)
2022 free(snd_card_name);
Dhananjay Kumara7e27832017-07-11 15:40:39 +05302023 if (mixer)
2024 mixer_close(mixer);
2025 if (hw_info)
2026 hw_info_deinit(hw_info);
Vignesh Kulothungan55396882017-04-20 14:37:02 -07002027
2028 if (snd_card_num >= MAX_SND_CARD) {
2029 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
2030 return -1;
2031 }
2032
2033 return snd_card_num;
2034}
Naresh Tanniru6160c712017-04-17 15:43:48 +05302035
2036#ifdef SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK
2037int audio_extn_utils_compress_enable_drift_correction(
2038 struct stream_out *out,
2039 struct audio_out_enable_drift_correction *drift)
2040{
2041 struct snd_compr_metadata metadata;
2042 int ret = -EINVAL;
2043
2044 if(drift == NULL) {
2045 ALOGE("%s:: Invalid param", __func__);
2046 goto exit;
2047 }
2048
2049 ALOGD("%s:: drift enable %d", __func__,drift->enable);
2050
2051 if (!is_offload_usecase(out->usecase)) {
2052 ALOGE("%s:: not supported for non offload session", __func__);
2053 goto exit;
2054 }
2055
2056 if (!out->compr) {
2057 ALOGW("%s:: offload session not yet opened,"
2058 "start delay will be configure later", __func__);
2059 goto exit;
2060 }
2061
2062 metadata.key = SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK;
2063 metadata.value[0] = drift->enable;
2064 out->drift_correction_enabled = drift->enable;
2065
2066 ret = compress_set_metadata(out->compr, &metadata);
2067 if(ret) {
2068 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
2069 out->drift_correction_enabled = false;
2070 }
2071
2072exit:
2073 return ret;
2074}
2075#else
2076int audio_extn_utils_compress_enable_drift_correction(
2077 struct stream_out *out __unused,
2078 struct audio_out_enable_drift_correction *drift __unused)
2079{
2080 ALOGD("%s:: configuring drift enablement not supported", __func__);
2081 return 0;
2082}
2083#endif
2084
2085#ifdef SNDRV_COMPRESS_ADJUST_SESSION_CLOCK
2086int audio_extn_utils_compress_correct_drift(
2087 struct stream_out *out,
2088 struct audio_out_correct_drift *drift_param)
2089{
2090 struct snd_compr_metadata metadata;
2091 int ret = -EINVAL;
2092
2093 if (drift_param == NULL) {
2094 ALOGE("%s:: Invalid drift_param", __func__);
2095 goto exit;
2096 }
2097
2098 ALOGD("%s:: adjust time 0x%"PRIx64" ", __func__,
2099 drift_param->adjust_time);
2100
2101 if (!is_offload_usecase(out->usecase)) {
2102 ALOGE("%s:: not supported for non offload session", __func__);
2103 goto exit;
2104 }
2105
2106 if (!out->compr) {
2107 ALOGW("%s:: offload session not yet opened", __func__);
2108 goto exit;
2109 }
2110
2111 if (!out->drift_correction_enabled) {
2112 ALOGE("%s:: drift correction not enabled", __func__);
2113 goto exit;
2114 }
2115
2116 metadata.key = SNDRV_COMPRESS_ADJUST_SESSION_CLOCK;
2117 metadata.value[0] = 0xFFFFFFFF & drift_param->adjust_time; /* lsb */
2118 metadata.value[1] = \
2119 (0xFFFFFFFF00000000 & drift_param->adjust_time) >> 32; /* msb*/
2120
2121 ret = compress_set_metadata(out->compr, &metadata);
2122 if(ret)
2123 ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
2124exit:
2125 return ret;
2126}
2127#else
2128int audio_extn_utils_compress_correct_drift(
2129 struct stream_out *out __unused,
2130 struct audio_out_correct_drift *drift_param __unused)
2131{
2132 ALOGD("%s:: setting adjust clock not supported", __func__);
2133 return 0;
2134}
2135#endif
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302136
2137int audio_extn_utils_set_channel_map(
2138 struct stream_out *out,
2139 struct audio_out_channel_map_param *channel_map_param)
2140{
2141 int ret = -EINVAL, i = 0;
2142 int channels = audio_channel_count_from_out_mask(out->channel_mask);
2143
2144 if (channel_map_param == NULL) {
2145 ALOGE("%s:: Invalid channel_map", __func__);
2146 goto exit;
2147 }
2148
2149 if (channel_map_param->channels != channels) {
2150 ALOGE("%s:: Channels(%d) does not match stream channels(%d)",
2151 __func__, channel_map_param->channels, channels);
2152 goto exit;
2153 }
2154
2155 for ( i = 0; i < channels; i++) {
2156 ALOGV("%s:: channel_map[%d]- %d", __func__, i, channel_map_param->channel_map[i]);
2157 out->channel_map_param.channel_map[i] = channel_map_param->channel_map[i];
2158 }
2159 ret = 0;
2160exit:
2161 return ret;
2162}