blob: 9ce0a695ceb75b4fd87c236f3543d0f70079f829 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
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.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530402 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500424 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400425
426 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
427 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
428 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700429};
430
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700431static const audio_usecase_t offload_usecases[] = {
432 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700433 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
436 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700441};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442
Varun Balaraje49253e2017-07-06 19:48:56 +0530443static const audio_usecase_t interactive_usecases[] = {
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
452};
453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454#define STRING_TO_ENUM(string) { #string, string }
455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456struct string_to_enum {
457 const char *name;
458 uint32_t value;
459};
460
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700461static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700470 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
471 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
472 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481};
482
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700483static const struct string_to_enum formats_name_to_enum_table[] = {
484 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
485 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
486 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700487 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
488 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
489 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700490 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800491 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
492 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700493 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800494};
495
496//list of all supported sample rates by HDMI specification.
497static const int out_hdmi_sample_rates[] = {
498 32000, 44100, 48000, 88200, 96000, 176400, 192000,
499};
500
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700501static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800502 STRING_TO_ENUM(32000),
503 STRING_TO_ENUM(44100),
504 STRING_TO_ENUM(48000),
505 STRING_TO_ENUM(88200),
506 STRING_TO_ENUM(96000),
507 STRING_TO_ENUM(176400),
508 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800509 STRING_TO_ENUM(352800),
510 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700511};
512
Carter Hsu2e429db2019-05-14 18:50:52 +0800513struct in_effect_list {
514 struct listnode list;
515 effect_handle_t handle;
516};
517
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700518static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700519static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700520static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700521//cache last MBDRC cal step level
522static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700523
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530524static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700525static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800526static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530527static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530528
Derek Chen6f293672019-04-01 01:40:24 -0700529static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
530static void in_snd_mon_cb(void * stream, struct str_parms * parms);
531static void out_snd_mon_cb(void * stream, struct str_parms * parms);
532
Zhou Song331c8e52019-08-26 14:16:12 +0800533static int configure_btsco_sample_rate(snd_device_t snd_device);
534
Vatsal Buchac09ae062018-11-14 13:25:08 +0530535#ifdef AUDIO_FEATURE_ENABLED_GCOV
536extern void __gcov_flush();
537static void enable_gcov()
538{
539 __gcov_flush();
540}
541#else
542static void enable_gcov()
543{
544}
545#endif
546
justinweng20fb6d82019-02-21 18:49:00 -0700547static int in_set_microphone_direction(const struct audio_stream_in *stream,
548 audio_microphone_direction_t dir);
549static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
550
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700551static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
552 int flags __unused)
553{
554 int dir = 0;
555 switch (uc_id) {
556 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530557 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700558 dir = 1;
559 case USECASE_AUDIO_PLAYBACK_ULL:
560 break;
561 default:
562 return false;
563 }
564
565 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
566 PCM_PLAYBACK : PCM_CAPTURE);
567 if (adev->adm_is_noirq_avail)
568 return adev->adm_is_noirq_avail(adev->adm_data,
569 adev->snd_card, dev_id, dir);
570 return false;
571}
572
573static void register_out_stream(struct stream_out *out)
574{
575 struct audio_device *adev = out->dev;
576 if (is_offload_usecase(out->usecase) ||
577 !adev->adm_register_output_stream)
578 return;
579
580 // register stream first for backward compatibility
581 adev->adm_register_output_stream(adev->adm_data,
582 out->handle,
583 out->flags);
584
585 if (!adev->adm_set_config)
586 return;
587
588 if (out->realtime)
589 adev->adm_set_config(adev->adm_data,
590 out->handle,
591 out->pcm, &out->config);
592}
593
594static void register_in_stream(struct stream_in *in)
595{
596 struct audio_device *adev = in->dev;
597 if (!adev->adm_register_input_stream)
598 return;
599
600 adev->adm_register_input_stream(adev->adm_data,
601 in->capture_handle,
602 in->flags);
603
604 if (!adev->adm_set_config)
605 return;
606
607 if (in->realtime)
608 adev->adm_set_config(adev->adm_data,
609 in->capture_handle,
610 in->pcm,
611 &in->config);
612}
613
614static void request_out_focus(struct stream_out *out, long ns)
615{
616 struct audio_device *adev = out->dev;
617
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618 if (adev->adm_request_focus_v2)
619 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
620 else if (adev->adm_request_focus)
621 adev->adm_request_focus(adev->adm_data, out->handle);
622}
623
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700625{
626 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700627 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629 if (adev->adm_request_focus_v2_1)
630 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
631 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700632 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
633 else if (adev->adm_request_focus)
634 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700635
636 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700637}
638
639static void release_out_focus(struct stream_out *out)
640{
641 struct audio_device *adev = out->dev;
642
643 if (adev->adm_abandon_focus)
644 adev->adm_abandon_focus(adev->adm_data, out->handle);
645}
646
647static void release_in_focus(struct stream_in *in)
648{
649 struct audio_device *adev = in->dev;
650 if (adev->adm_abandon_focus)
651 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
652}
653
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530654static int parse_snd_card_status(struct str_parms *parms, int *card,
655 card_status_t *status)
656{
657 char value[32]={0};
658 char state[32]={0};
659
660 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
661 if (ret < 0)
662 return -1;
663
664 // sscanf should be okay as value is of max length 32.
665 // same as sizeof state.
666 if (sscanf(value, "%d,%s", card, state) < 2)
667 return -1;
668
669 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
670 CARD_STATUS_OFFLINE;
671 return 0;
672}
673
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700674static inline void adjust_frames_for_device_delay(struct stream_out *out,
675 uint32_t *dsp_frames) {
676 // Adjustment accounts for A2dp encoder latency with offload usecases
677 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800678 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700679 unsigned long offset =
680 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
681 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
682 }
683}
684
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700685static inline bool free_entry(void *key __unused,
686 void *value, void *context __unused)
687{
688 free(value);
689 return true;
690}
691
692static inline void free_map(Hashmap *map)
693{
694 if (map) {
695 hashmapForEach(map, free_entry, (void *) NULL);
696 hashmapFree(map);
697 }
698}
699
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800700static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 audio_patch_handle_t patch_handle)
702{
703 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
704 return;
705
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700706 struct audio_patch_info *p_info =
707 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
708 if (p_info) {
709 ALOGV("%s: Remove patch %d", __func__, patch_handle);
710 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
711 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700712 free(p_info);
713 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700714}
715
716static inline int io_streams_map_insert(struct audio_device *adev,
717 struct audio_stream *stream,
718 audio_io_handle_t handle,
719 audio_patch_handle_t patch_handle)
720{
721 struct audio_stream_info *s_info =
722 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
723
724 if (s_info == NULL) {
725 ALOGE("%s: Could not allocate stream info", __func__);
726 return -ENOMEM;
727 }
728 s_info->stream = stream;
729 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730
731 pthread_mutex_lock(&adev->lock);
732 struct audio_stream_info *stream_info =
733 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 if (stream_info != NULL)
735 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800736 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700737 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 return 0;
739}
740
741static inline void io_streams_map_remove(struct audio_device *adev,
742 audio_io_handle_t handle)
743{
744 pthread_mutex_lock(&adev->lock);
745 struct audio_stream_info *s_info =
746 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800748 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700749 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800750 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700751 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800752done:
753 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 return;
755}
756
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800757static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700758 audio_patch_handle_t handle)
759{
760 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700761 p_info = (struct audio_patch_info *)
762 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700763 return p_info;
764}
765
vivek mehtaa76401a2015-04-24 14:12:15 -0700766__attribute__ ((visibility ("default")))
767bool audio_hw_send_gain_dep_calibration(int level) {
768 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700769 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700770
771 pthread_mutex_lock(&adev_init_lock);
772
773 if (adev != NULL && adev->platform != NULL) {
774 pthread_mutex_lock(&adev->lock);
775 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700776
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530777 // cache level info for any of the use case which
778 // was not started.
779 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700780
vivek mehtaa76401a2015-04-24 14:12:15 -0700781 pthread_mutex_unlock(&adev->lock);
782 } else {
783 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
784 }
785
786 pthread_mutex_unlock(&adev_init_lock);
787
788 return ret_val;
789}
790
Ashish Jain5106d362016-05-11 19:23:33 +0530791static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
792{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800793 bool gapless_enabled = false;
794 const char *mixer_ctl_name = "Compress Gapless Playback";
795 struct mixer_ctl *ctl;
796
797 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700798 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530799
800 /*Disable gapless if its AV playback*/
801 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800802
803 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
804 if (!ctl) {
805 ALOGE("%s: Could not get ctl for mixer cmd - %s",
806 __func__, mixer_ctl_name);
807 return -EINVAL;
808 }
809
810 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
811 ALOGE("%s: Could not set gapless mode %d",
812 __func__, gapless_enabled);
813 return -EINVAL;
814 }
815 return 0;
816}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700817
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700818__attribute__ ((visibility ("default")))
819int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
820 int table_size) {
821 int ret_val = 0;
822 ALOGV("%s: enter ... ", __func__);
823
824 pthread_mutex_lock(&adev_init_lock);
825 if (adev == NULL) {
826 ALOGW("%s: adev is NULL .... ", __func__);
827 goto done;
828 }
829
830 pthread_mutex_lock(&adev->lock);
831 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
832 pthread_mutex_unlock(&adev->lock);
833done:
834 pthread_mutex_unlock(&adev_init_lock);
835 ALOGV("%s: exit ... ", __func__);
836 return ret_val;
837}
838
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800839bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800840{
841 bool ret = false;
842 ALOGV("%s: enter ...", __func__);
843
844 pthread_mutex_lock(&adev_init_lock);
845
846 if (adev != NULL && adev->platform != NULL) {
847 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800848 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800849 pthread_mutex_unlock(&adev->lock);
850 }
851
852 pthread_mutex_unlock(&adev_init_lock);
853
854 ALOGV("%s: exit with ret %d", __func__, ret);
855 return ret;
856}
Aalique Grahame22e49102018-12-18 14:23:57 -0800857
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700858static bool is_supported_format(audio_format_t format)
859{
Eric Laurent86e17132013-09-12 17:49:30 -0700860 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530861 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530862 format == AUDIO_FORMAT_AAC_LC ||
863 format == AUDIO_FORMAT_AAC_HE_V1 ||
864 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530865 format == AUDIO_FORMAT_AAC_ADTS_LC ||
866 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
867 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530868 format == AUDIO_FORMAT_AAC_LATM_LC ||
869 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
870 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530871 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
872 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530873 format == AUDIO_FORMAT_PCM_FLOAT ||
874 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700875 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530876 format == AUDIO_FORMAT_AC3 ||
877 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700878 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530879 format == AUDIO_FORMAT_DTS ||
880 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800881 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530882 format == AUDIO_FORMAT_ALAC ||
883 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530884 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530885 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800886 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530887 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700888 format == AUDIO_FORMAT_APTX ||
889 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800890 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700891
892 return false;
893}
894
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700895static inline bool is_mmap_usecase(audio_usecase_t uc_id)
896{
897 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800898 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700899 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
900}
901
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700902static inline bool is_valid_volume(float left, float right)
903{
904 return ((left >= 0.0f && right >= 0.0f) ? true : false);
905}
906
Avinash Vaish71a8b972014-07-24 15:36:33 +0530907static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
908 struct audio_usecase *uc_info)
909{
910 struct listnode *node;
911 struct audio_usecase *usecase;
912
913 if (uc_info == NULL)
914 return -EINVAL;
915
916 /* Re-route all voice usecases on the shared backend other than the
917 specified usecase to new snd devices */
918 list_for_each(node, &adev->usecase_list) {
919 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800920 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530921 enable_audio_route(adev, usecase);
922 }
923 return 0;
924}
925
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530926static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530927{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530928 ALOGV("%s", __func__);
929 audio_route_apply_and_update_path(adev->audio_route,
930 "asrc-mode");
931 adev->asrc_mode_enabled = true;
932}
933
934static void disable_asrc_mode(struct audio_device *adev)
935{
936 ALOGV("%s", __func__);
937 audio_route_reset_and_update_path(adev->audio_route,
938 "asrc-mode");
939 adev->asrc_mode_enabled = false;
940}
941
Saurav Kumarc1411662020-10-14 10:50:45 +0530942static void check_and_configure_headphone(struct audio_device *adev,
943 struct audio_usecase *uc_info,
944 snd_device_t snd_device)
945{
946 struct listnode *node;
947 struct audio_usecase *usecase;
948 int new_backend_idx, usecase_backend_idx;
949 bool spkr_hph_single_be_native_concurrency;
950
951 new_backend_idx = platform_get_backend_index(snd_device);
952 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
953 if ( spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) {
954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
957 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
958 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
959 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
960 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->out_snd_device);
963 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
964 enable_audio_route(adev, usecase);
965 enable_snd_device(adev, usecase->out_snd_device);
966 }
967 }
968 }
969 }
970}
971
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530972/*
973 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
974 * 44.1 or Native DSD backends are enabled for any of current use case.
975 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
976 * - Disable current mix path use case(Headphone backend) and re-enable it with
977 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
978 * e.g. Naitve DSD or Headphone 44.1 -> + 48
979 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530980static void check_and_set_asrc_mode(struct audio_device *adev,
981 struct audio_usecase *uc_info,
982 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530983{
984 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530985 int i, num_new_devices = 0;
986 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
987 /*
988 *Split snd device for new combo use case
989 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
990 */
991 if (platform_split_snd_device(adev->platform,
992 snd_device,
993 &num_new_devices,
994 split_new_snd_devices) == 0) {
995 for (i = 0; i < num_new_devices; i++)
996 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
997 } else {
998 int new_backend_idx = platform_get_backend_index(snd_device);
999 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1000 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1001 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1002 !adev->asrc_mode_enabled) {
1003 struct listnode *node = NULL;
1004 struct audio_usecase *uc = NULL;
1005 struct stream_out *curr_out = NULL;
1006 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1007 int i, num_devices, ret = 0;
1008 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301009
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301010 list_for_each(node, &adev->usecase_list) {
1011 uc = node_to_item(node, struct audio_usecase, list);
1012 curr_out = (struct stream_out*) uc->stream.out;
1013 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1014 /*
1015 *Split snd device for existing combo use case
1016 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1017 */
1018 ret = platform_split_snd_device(adev->platform,
1019 uc->out_snd_device,
1020 &num_devices,
1021 split_snd_devices);
1022 if (ret < 0 || num_devices == 0) {
1023 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1024 split_snd_devices[0] = uc->out_snd_device;
1025 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001026 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301027 for (i = 0; i < num_devices; i++) {
1028 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1029 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1030 if((new_backend_idx == HEADPHONE_BACKEND) &&
1031 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1032 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001033 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301034 __func__);
1035 enable_asrc_mode(adev);
1036 break;
1037 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1038 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1039 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001040 ALOGV("%s: 48K stream detected, disabling and enabling it \
1041 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301042 disable_audio_route(adev, uc);
1043 disable_snd_device(adev, uc->out_snd_device);
1044 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1045 if (new_backend_idx == DSD_NATIVE_BACKEND)
1046 audio_route_apply_and_update_path(adev->audio_route,
1047 "hph-true-highquality-mode");
1048 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1049 (curr_out->bit_width >= 24))
1050 audio_route_apply_and_update_path(adev->audio_route,
1051 "hph-highquality-mode");
1052 enable_asrc_mode(adev);
1053 enable_snd_device(adev, uc->out_snd_device);
1054 enable_audio_route(adev, uc);
1055 break;
1056 }
1057 }
1058 // reset split devices count
1059 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001060 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301061 if (adev->asrc_mode_enabled)
1062 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301063 }
1064 }
1065 }
1066}
1067
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1069 struct audio_effect_config effect_config,
1070 unsigned int param_value)
1071{
1072 char mixer_ctl_name[] = "Audio Effect";
1073 struct mixer_ctl *ctl;
1074 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001075 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001076
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001077 if (in == NULL) {
1078 ALOGE("%s: active input stream is NULL", __func__);
1079 return -EINVAL;
1080 }
1081
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001082 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1083 if (!ctl) {
1084 ALOGE("%s: Could not get mixer ctl - %s",
1085 __func__, mixer_ctl_name);
1086 return -EINVAL;
1087 }
1088
1089 set_values[0] = 1; //0:Rx 1:Tx
1090 set_values[1] = in->app_type_cfg.app_type;
1091 set_values[2] = (long)effect_config.module_id;
1092 set_values[3] = (long)effect_config.instance_id;
1093 set_values[4] = (long)effect_config.param_id;
1094 set_values[5] = param_value;
1095
1096 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1097
1098 return 0;
1099
1100}
1101
1102static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1103 int effect_type, unsigned int *param_value)
1104{
1105 int ret = 0;
1106 struct audio_effect_config other_effect_config;
1107 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001108 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001109
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001110 if (in == NULL) {
1111 ALOGE("%s: active input stream is NULL", __func__);
1112 return -EINVAL;
1113 }
1114
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001115 usecase = get_usecase_from_list(adev, in->usecase);
1116 if (!usecase)
1117 return -EINVAL;
1118
1119 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1120 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1121 if (ret < 0) {
1122 ALOGE("%s Failed to get effect params %d", __func__, ret);
1123 return ret;
1124 }
1125
1126 if (module_id == other_effect_config.module_id) {
1127 //Same module id for AEC/NS. Values need to be combined
1128 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1129 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1130 *param_value |= other_effect_config.param_value;
1131 }
1132 }
1133
1134 return ret;
1135}
1136
1137static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301138{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001139 struct audio_effect_config effect_config;
1140 struct audio_usecase *usecase = NULL;
1141 int ret = 0;
1142 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001143 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001144
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001145 if(!voice_extn_is_dynamic_ecns_enabled())
1146 return ENOSYS;
1147
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001148 if (!in) {
1149 ALOGE("%s: Invalid input stream", __func__);
1150 return -EINVAL;
1151 }
1152
1153 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1154
1155 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001156 if (usecase == NULL) {
1157 ALOGE("%s: Could not find the usecase (%d) in the list",
1158 __func__, in->usecase);
1159 return -EINVAL;
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161
1162 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1163 if (ret < 0) {
1164 ALOGE("%s Failed to get module id %d", __func__, ret);
1165 return ret;
1166 }
1167 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1168 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1169
1170 if(enable)
1171 param_value = effect_config.param_value;
1172
1173 /*Special handling for AEC & NS effects Param values need to be
1174 updated if module ids are same*/
1175
1176 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1177 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1178 if (ret < 0)
1179 return ret;
1180 }
1181
1182 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1183
1184 return ret;
1185}
1186
1187static void check_and_enable_effect(struct audio_device *adev)
1188{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001189 if(!voice_extn_is_dynamic_ecns_enabled())
1190 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001191
Eric Laurent637e2d42018-11-15 12:24:31 -08001192 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001193
Eric Laurent637e2d42018-11-15 12:24:31 -08001194 if (in != NULL && !in->standby) {
1195 if (in->enable_aec)
1196 enable_disable_effect(adev, EFFECT_AEC, true);
1197
1198 if (in->enable_ns &&
1199 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1200 enable_disable_effect(adev, EFFECT_NS, true);
1201 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001202 }
1203}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001205int pcm_ioctl(struct pcm *pcm, int request, ...)
1206{
1207 va_list ap;
1208 void * arg;
1209 int pcm_fd = *(int*)pcm;
1210
1211 va_start(ap, request);
1212 arg = va_arg(ap, void *);
1213 va_end(ap);
1214
1215 return ioctl(pcm_fd, request, arg);
1216}
1217
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001218int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001219 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001221 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001222 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301223 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301224 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001225 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301226 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001227
1228 if (usecase == NULL)
1229 return -EINVAL;
1230
1231 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1232
Carter Hsu2e429db2019-05-14 18:50:52 +08001233 if (usecase->type == PCM_CAPTURE) {
1234 struct stream_in *in = usecase->stream.in;
1235 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001237
1238 if (in) {
1239 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001240 list_init(&out_devices);
1241 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001242 struct listnode *node;
1243 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1244 USECASE_AUDIO_PLAYBACK_VOIP);
1245 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001246 assign_devices(&out_devices,
1247 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001248 } else if (adev->primary_output &&
1249 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001250 assign_devices(&out_devices,
1251 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001252 } else {
1253 list_for_each(node, &adev->usecase_list) {
1254 uinfo = node_to_item(node, struct audio_usecase, list);
1255 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001256 assign_devices(&out_devices,
1257 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001258 break;
1259 }
1260 }
1261 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001262
1263 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001264 in->ec_opened = true;
1265 }
1266 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001267 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1268 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1269 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001270 snd_device = usecase->in_snd_device;
1271 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001273 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001274
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001275#ifdef DS1_DOLBY_DAP_ENABLED
1276 audio_extn_dolby_set_dmid(adev);
1277 audio_extn_dolby_set_endpoint(adev);
1278#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001279 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001280 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301281 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001282 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001283 if (audio_extn_is_maxx_audio_enabled())
1284 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301285 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301286 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1287 out = usecase->stream.out;
1288 if (out && out->compr)
1289 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1290 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301291
1292 if (usecase->type == PCM_CAPTURE) {
1293 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001294 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301295 ALOGD("%s: set custom mtmx params v1", __func__);
1296 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1297 }
1298 } else {
1299 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1300 }
Manish Dewangan58229382017-02-02 15:48:41 +05301301
Andy Hung756ecc12018-10-19 17:47:12 -07001302 // we shouldn't truncate mixer_path
1303 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1304 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1305 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001306 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001307 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301308 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1309 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1310 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1311 if (parms) {
1312 audio_extn_fm_set_parameters(adev, parms);
1313 str_parms_destroy(parms);
1314 }
1315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316 ALOGV("%s: exit", __func__);
1317 return 0;
1318}
1319
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001320int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001321 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001324 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301325 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001326
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301327 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001328 return -EINVAL;
1329
1330 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301331 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001332 snd_device = usecase->in_snd_device;
1333 else
1334 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001335
1336 /* disable island and power mode on supported device for voice call */
1337 if (usecase->type == VOICE_CALL) {
1338 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1339 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1340 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1341 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1342 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1343 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001344 if (voice_is_lte_call_active(adev))
1345 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001346 ALOGD("%s: disable island cfg and power mode in voice tx path",
1347 __func__);
1348 }
1349 }
1350 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1351 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1352 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1353 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1354 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1355 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1356 ALOGD("%s: disable island cfg and power mode in voice rx path",
1357 __func__);
1358 }
1359 }
1360 }
1361
Andy Hung756ecc12018-10-19 17:47:12 -07001362 // we shouldn't truncate mixer_path
1363 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1364 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1365 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001366 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001367 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001368 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001369 if (usecase->type == PCM_CAPTURE) {
1370 struct stream_in *in = usecase->stream.in;
1371 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001372 struct listnode out_devices;
1373 list_init(&out_devices);
1374 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001375 in->ec_opened = false;
1376 }
1377 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001378 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301379 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301380
1381 if (usecase->type == PCM_CAPTURE) {
1382 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001383 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301384 ALOGD("%s: reset custom mtmx params v1", __func__);
1385 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1386 }
1387 } else {
1388 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1389 }
1390
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001391 if ((usecase->type == PCM_PLAYBACK) &&
1392 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301393 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 ALOGV("%s: exit", __func__);
1396 return 0;
1397}
1398
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001399int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301402 int i, num_devices = 0;
1403 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001404 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1405
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001406 if (snd_device < SND_DEVICE_MIN ||
1407 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001408 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001409 return -EINVAL;
1410 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001412 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001413 ALOGE("%s: Invalid sound device returned", __func__);
1414 return -EINVAL;
1415 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001416
1417 adev->snd_dev_ref_cnt[snd_device]++;
1418
1419 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1420 (platform_split_snd_device(adev->platform,
1421 snd_device,
1422 &num_devices,
1423 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001424 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001425 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001426 /* Set backend config for A2DP to ensure slimbus configuration
1427 is correct if A2DP is already active and backend is closed
1428 and re-opened */
1429 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1430 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 return 0;
1432 }
1433
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001434 if (audio_extn_spkr_prot_is_enabled())
1435 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001436
Aalique Grahame22e49102018-12-18 14:23:57 -08001437 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1438
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001439 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1440 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001441 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1442 goto err;
1443 }
1444 audio_extn_dev_arbi_acquire(snd_device);
1445 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001446 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001447 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001448 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001449 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001450 } else if (platform_split_snd_device(adev->platform,
1451 snd_device,
1452 &num_devices,
1453 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301454 for (i = 0; i < num_devices; i++) {
1455 enable_snd_device(adev, new_snd_devices[i]);
1456 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001457 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001458 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001459 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301460
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001461 /* enable island and power mode on supported device */
1462 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1463 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1464 platform_set_island_cfg_on_device(adev, snd_device, true);
1465 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001466 if (voice_is_lte_call_active(adev) &&
1467 (snd_device >= SND_DEVICE_IN_BEGIN &&
1468 snd_device < SND_DEVICE_IN_END))
1469 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001470 ALOGD("%s: enable island cfg and power mode on: %s",
1471 __func__, device_name);
1472 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301473
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301474 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1475 if (audio_extn_a2dp_start_playback() < 0) {
1476 ALOGE(" fail to configure A2dp Source control path ");
1477 goto err;
1478 } else {
1479 adev->a2dp_started = true;
1480 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001481 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001482
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001483 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1484 (audio_extn_a2dp_start_capture() < 0)) {
1485 ALOGE(" fail to configure A2dp Sink control path ");
1486 goto err;
1487 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301488
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001489 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1490 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1491 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1492 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1493 ALOGE(" fail to configure sco control path ");
1494 goto err;
1495 }
Zhou Song12c29502019-03-16 10:37:18 +08001496 }
1497
Zhou Song331c8e52019-08-26 14:16:12 +08001498 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001499 /* due to the possibility of calibration overwrite between listen
1500 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001501 audio_extn_sound_trigger_update_device_status(snd_device,
1502 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301503 audio_extn_listen_update_device_status(snd_device,
1504 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001505 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001506 audio_extn_sound_trigger_update_device_status(snd_device,
1507 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301508 audio_extn_listen_update_device_status(snd_device,
1509 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001510 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001511 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001512 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001513 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301514
1515 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1516 !adev->native_playback_enabled &&
1517 audio_is_true_native_stream_active(adev)) {
1518 ALOGD("%s: %d: napb: enabling native mode in hardware",
1519 __func__, __LINE__);
1520 audio_route_apply_and_update_path(adev->audio_route,
1521 "true-native-mode");
1522 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301523 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301524 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1525 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001526 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001527 ALOGD("%s: init ec ref loopback", __func__);
1528 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532err:
1533 adev->snd_dev_ref_cnt[snd_device]--;
1534 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535}
1536
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001537int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001538 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301540 int i, num_devices = 0;
1541 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001542 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1543
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001544 if (snd_device < SND_DEVICE_MIN ||
1545 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001546 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001547 return -EINVAL;
1548 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001549
1550 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1551 ALOGE("%s: Invalid sound device returned", __func__);
1552 return -EINVAL;
1553 }
1554
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1556 ALOGE("%s: device ref cnt is already 0", __func__);
1557 return -EINVAL;
1558 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001559
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001561
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001564 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301565
Aalique Grahame22e49102018-12-18 14:23:57 -08001566 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1567
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001568 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1569 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001570 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001571
1572 // when speaker device is disabled, reset swap.
1573 // will be renabled on usecase start
1574 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001575 } else if (platform_split_snd_device(adev->platform,
1576 snd_device,
1577 &num_devices,
1578 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301579 for (i = 0; i < num_devices; i++) {
1580 disable_snd_device(adev, new_snd_devices[i]);
1581 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001582 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001583 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001584 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001585 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001586
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301587 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301588 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301589 adev->a2dp_started = false;
1590 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001591 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001592 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001593 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301594 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001595 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301596 adev->native_playback_enabled) {
1597 ALOGD("%s: %d: napb: disabling native mode in hardware",
1598 __func__, __LINE__);
1599 audio_route_reset_and_update_path(adev->audio_route,
1600 "true-native-mode");
1601 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001602 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301603 adev->asrc_mode_enabled) {
1604 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301605 disable_asrc_mode(adev);
1606 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001607 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301608 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001609 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001610 ALOGD("%s: deinit ec ref loopback", __func__);
1611 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1612 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001613
1614 audio_extn_utils_release_snd_device(snd_device);
1615 } else {
1616 if (platform_split_snd_device(adev->platform,
1617 snd_device,
1618 &num_devices,
1619 new_snd_devices) == 0) {
1620 for (i = 0; i < num_devices; i++) {
1621 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1622 }
1623 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 return 0;
1627}
1628
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001629/*
1630 legend:
1631 uc - existing usecase
1632 new_uc - new usecase
1633 d1, d11, d2 - SND_DEVICE enums
1634 a1, a2 - corresponding ANDROID device enums
1635 B1, B2 - backend strings
1636
1637case 1
1638 uc->dev d1 (a1) B1
1639 new_uc->dev d1 (a1), d2 (a2) B1, B2
1640
1641 resolution: disable and enable uc->dev on d1
1642
1643case 2
1644 uc->dev d1 (a1) B1
1645 new_uc->dev d11 (a1) B1
1646
1647 resolution: need to switch uc since d1 and d11 are related
1648 (e.g. speaker and voice-speaker)
1649 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1650
1651case 3
1652 uc->dev d1 (a1) B1
1653 new_uc->dev d2 (a2) B2
1654
1655 resolution: no need to switch uc
1656
1657case 4
1658 uc->dev d1 (a1) B1
1659 new_uc->dev d2 (a2) B1
1660
1661 resolution: disable enable uc-dev on d2 since backends match
1662 we cannot enable two streams on two different devices if they
1663 share the same backend. e.g. if offload is on speaker device using
1664 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1665 using the same backend, offload must also be switched to voice-handset.
1666
1667case 5
1668 uc->dev d1 (a1) B1
1669 new_uc->dev d1 (a1), d2 (a2) B1
1670
1671 resolution: disable enable uc-dev on d2 since backends match
1672 we cannot enable two streams on two different devices if they
1673 share the same backend.
1674
1675case 6
1676 uc->dev d1 (a1) B1
1677 new_uc->dev d2 (a1) B2
1678
1679 resolution: no need to switch
1680
1681case 7
1682 uc->dev d1 (a1), d2 (a2) B1, B2
1683 new_uc->dev d1 (a1) B1
1684
1685 resolution: no need to switch
1686
Zhou Song4ba65882018-07-09 14:48:07 +08001687case 8
1688 uc->dev d1 (a1) B1
1689 new_uc->dev d11 (a1), d2 (a2) B1, B2
1690 resolution: compared to case 1, for this case, d1 and d11 are related
1691 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301692
1693case 9
1694 uc->dev d1 (a1), d2(a2) B1 B2
1695 new_uc->dev d1 (a1), d22 (a2) B1, B2
1696 resolution: disable enable uc-dev on d2 since backends match
1697 we cannot enable two streams on two different devices if they
1698 share the same backend. This is special case for combo use case
1699 with a2dp and sco devices which uses same backend.
1700 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701*/
1702static snd_device_t derive_playback_snd_device(void * platform,
1703 struct audio_usecase *uc,
1704 struct audio_usecase *new_uc,
1705 snd_device_t new_snd_device)
1706{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001707 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001708
1709 snd_device_t d1 = uc->out_snd_device;
1710 snd_device_t d2 = new_snd_device;
1711
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001712 list_init(&a1);
1713 list_init(&a2);
1714
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301715 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301716 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001717 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1718 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301719 break;
1720 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001721 assign_devices(&a1, &uc->stream.out->device_list);
1722 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301723 break;
1724 }
1725
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001726 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001727 if (!compare_devices(&a1, &a2) &&
1728 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001729 snd_device_t d3[2];
1730 int num_devices = 0;
1731 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001732 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001733 &num_devices,
1734 d3);
1735 if (ret < 0) {
1736 if (ret != -ENOSYS) {
1737 ALOGW("%s failed to split snd_device %d",
1738 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001739 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001740 }
1741 goto end;
1742 }
1743
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001744 if (platform_check_backends_match(d3[0], d3[1])) {
1745 return d2; // case 5
1746 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301747 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1748 platform_check_backends_match(d1, d2))
1749 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001750 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301751 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001752 // check if d1 is related to any of d3's
1753 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001754 return d1; // case 1
1755 else
1756 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001757 }
1758 } else {
1759 if (platform_check_backends_match(d1, d2)) {
1760 return d2; // case 2, 4
1761 } else {
1762 return d1; // case 6, 3
1763 }
1764 }
1765
1766end:
1767 return d2; // return whatever was calculated before.
1768}
1769
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301771 struct audio_usecase *uc_info,
1772 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773{
1774 struct listnode *node;
1775 struct audio_usecase *usecase;
1776 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301777 snd_device_t uc_derive_snd_device;
1778 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001779 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1780 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001781 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301782 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001783 /*
1784 * This function is to make sure that all the usecases that are active on
1785 * the hardware codec backend are always routed to any one device that is
1786 * handled by the hardware codec.
1787 * For example, if low-latency and deep-buffer usecases are currently active
1788 * on speaker and out_set_parameters(headset) is received on low-latency
1789 * output, then we have to make sure deep-buffer is also switched to headset,
1790 * because of the limitation that both the devices cannot be enabled
1791 * at the same time as they share the same backend.
1792 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001793 /*
1794 * This call is to check if we need to force routing for a particular stream
1795 * If there is a backend configuration change for the device when a
1796 * new stream starts, then ADM needs to be closed and re-opened with the new
1797 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001798 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001799 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001800 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1801 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301802 /* For a2dp device reconfigure all active sessions
1803 * with new AFE encoder format based on a2dp state
1804 */
1805 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301806 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1807 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301808 audio_extn_a2dp_is_force_device_switch()) {
1809 force_routing = true;
1810 force_restart_session = true;
1811 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001812
1813 /*
1814 * Island cfg and power mode config needs to set before AFE port start.
1815 * Set force routing in case of voice device was enable before.
1816 */
1817 if (uc_info->type == VOICE_CALL &&
1818 voice_extn_is_voice_power_mode_supported() &&
1819 platform_check_and_update_island_power_status(adev->platform,
1820 uc_info,
1821 snd_device)) {
1822 force_routing = true;
1823 ALOGD("%s:becf: force routing %d for power mode supported device",
1824 __func__, force_routing);
1825 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301826 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001829 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001830 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1832 switch_device[i] = false;
1833
1834 list_for_each(node, &adev->usecase_list) {
1835 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001836
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301837 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1838 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301839 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301840 platform_get_snd_device_name(usecase->out_snd_device),
1841 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301842 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1843 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301844 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1845 usecase, uc_info, snd_device);
1846 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001847 (is_codec_backend_out_device_type(&usecase->device_list) ||
1848 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1849 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1850 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1851 is_a2dp_out_device_type(&usecase->device_list) ||
1852 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301853 ((force_restart_session) ||
1854 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301855 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1856 __func__, use_case_table[usecase->id],
1857 platform_get_snd_device_name(usecase->out_snd_device));
1858 disable_audio_route(adev, usecase);
1859 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301860 /* Enable existing usecase on derived playback device */
1861 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301862 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001864 }
1865 }
1866
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301867 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1868 num_uc_to_switch);
1869
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001871 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301873 /* Make sure the previous devices to be disabled first and then enable the
1874 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875 list_for_each(node, &adev->usecase_list) {
1876 usecase = node_to_item(node, struct audio_usecase, list);
1877 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001878 /* Check if output sound device to be switched can be split and if any
1879 of the split devices match with derived sound device */
1880 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1881 &num_devices, split_snd_devices) == 0) {
1882 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1883 for (i = 0; i < num_devices; i++) {
1884 /* Disable devices that do not match with derived sound device */
1885 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1886 disable_snd_device(adev, split_snd_devices[i]);
1887 }
1888 } else {
1889 disable_snd_device(adev, usecase->out_snd_device);
1890 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 }
1892 }
1893
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001894 list_for_each(node, &adev->usecase_list) {
1895 usecase = node_to_item(node, struct audio_usecase, list);
1896 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001897 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1898 &num_devices, split_snd_devices) == 0) {
1899 /* Enable derived sound device only if it does not match with
1900 one of the split sound devices. This is because the matching
1901 sound device was not disabled */
1902 bool should_enable = true;
1903 for (i = 0; i < num_devices; i++) {
1904 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1905 should_enable = false;
1906 break;
1907 }
1908 }
1909 if (should_enable)
1910 enable_snd_device(adev, derive_snd_device[usecase->id]);
1911 } else {
1912 enable_snd_device(adev, derive_snd_device[usecase->id]);
1913 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001914 }
1915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001917 /* Re-route all the usecases on the shared backend other than the
1918 specified usecase to new snd devices */
1919 list_for_each(node, &adev->usecase_list) {
1920 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301921 /* Update the out_snd_device only before enabling the audio route */
1922 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301923 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301924 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301925 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301926 use_case_table[usecase->id],
1927 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001928 /* Update voc calibration before enabling VoIP route */
1929 if (usecase->type == VOIP_CALL)
1930 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001931 usecase->out_snd_device,
1932 platform_get_input_snd_device(
1933 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301934 &uc_info->device_list,
1935 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301936 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301937 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001938 out_set_voip_volume(&usecase->stream.out->stream,
1939 usecase->stream.out->volume_l,
1940 usecase->stream.out->volume_r);
1941 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301942 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943 }
1944 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001945 }
1946}
1947
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301948static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001949 struct audio_usecase *uc_info,
1950 snd_device_t snd_device)
1951{
1952 struct listnode *node;
1953 struct audio_usecase *usecase;
1954 bool switch_device[AUDIO_USECASE_MAX];
1955 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001956 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001957 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001958
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301959 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1960 snd_device);
1961 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301962
1963 /*
1964 * Make sure out devices is checked against out codec backend device and
1965 * also in devices against in codec backend. Checking out device against in
1966 * codec backend or vice versa causes issues.
1967 */
1968 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001969 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001970
1971 /*
1972 * Island cfg and power mode config needs to set before AFE port start.
1973 * Set force routing in case of voice device was enable before.
1974 */
1975
1976 if (uc_info->type == VOICE_CALL &&
1977 voice_extn_is_voice_power_mode_supported() &&
1978 platform_check_and_update_island_power_status(adev->platform,
1979 uc_info,
1980 snd_device)) {
1981 force_routing = true;
1982 ALOGD("%s:becf: force routing %d for power mode supported device",
1983 __func__, force_routing);
1984 }
1985
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001986 /*
1987 * This function is to make sure that all the active capture usecases
1988 * are always routed to the same input sound device.
1989 * For example, if audio-record and voice-call usecases are currently
1990 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1991 * is received for voice call then we have to make sure that audio-record
1992 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1993 * because of the limitation that two devices cannot be enabled
1994 * at the same time if they share the same backend.
1995 */
1996 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1997 switch_device[i] = false;
1998
1999 list_for_each(node, &adev->usecase_list) {
2000 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302001 /*
2002 * TODO: Enhance below condition to handle BT sco/USB multi recording
2003 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302004
2005 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2006 (usecase->in_snd_device != snd_device || force_routing));
2007 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2008 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2009 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002010 ((backend_check_cond &&
2011 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002012 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002013 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002014 is_single_device_type_equal(&usecase->device_list,
2015 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002016 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002017 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002018 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302019 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002020 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002021 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002022 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002023 switch_device[usecase->id] = true;
2024 num_uc_to_switch++;
2025 }
2026 }
2027
2028 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002029 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002030
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302031 /* Make sure the previous devices to be disabled first and then enable the
2032 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002033 list_for_each(node, &adev->usecase_list) {
2034 usecase = node_to_item(node, struct audio_usecase, list);
2035 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002036 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002037 }
2038 }
2039
2040 list_for_each(node, &adev->usecase_list) {
2041 usecase = node_to_item(node, struct audio_usecase, list);
2042 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002043 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002044 }
2045 }
2046
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002047 /* Re-route all the usecases on the shared backend other than the
2048 specified usecase to new snd devices */
2049 list_for_each(node, &adev->usecase_list) {
2050 usecase = node_to_item(node, struct audio_usecase, list);
2051 /* Update the in_snd_device only before enabling the audio route */
2052 if (switch_device[usecase->id] ) {
2053 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002054 if (usecase->type != VOICE_CALL) {
2055 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302056 if (usecase->type == VOIP_CALL) {
2057 snd_device_t voip_snd_device;
2058 voip_snd_device = platform_get_output_snd_device(adev->platform,
2059 uc_info->stream.out,
2060 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002061 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302062 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002063 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302064 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302065 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002066 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002067 }
2068 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002069 }
2070}
2071
Mingming Yin3a941d42016-02-17 18:08:05 -08002072static void reset_hdmi_sink_caps(struct stream_out *out) {
2073 int i = 0;
2074
2075 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2076 out->supported_channel_masks[i] = 0;
2077 }
2078 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2079 out->supported_formats[i] = 0;
2080 }
2081 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2082 out->supported_sample_rates[i] = 0;
2083 }
2084}
2085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002087static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088{
Mingming Yin3a941d42016-02-17 18:08:05 -08002089 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002090 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2091 out->extconn.cs.controller,
2092 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093
Mingming Yin3a941d42016-02-17 18:08:05 -08002094 reset_hdmi_sink_caps(out);
2095
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002096 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002097 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002098 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002099 out->extconn.cs.stream);
2100 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002101 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002102 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002103 }
2104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002107 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002108 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002109 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2110 case 6:
2111 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2112 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2113 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2114 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2115 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2116 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 break;
2118 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002119 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002120 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 break;
2122 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002123
2124 // check channel format caps
2125 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002126 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2127 out->extconn.cs.controller,
2128 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002129 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2130 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2131 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2132 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2133 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2134 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2135 }
2136
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002137 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2138 out->extconn.cs.controller,
2139 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002140 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2141 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2142 }
2143
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002144 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2145 out->extconn.cs.controller,
2146 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002147 ALOGV(":%s HDMI supports DTS format", __func__);
2148 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2149 }
2150
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002151 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2152 out->extconn.cs.controller,
2153 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002154 ALOGV(":%s HDMI supports DTS HD format", __func__);
2155 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2156 }
2157
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002158 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2159 out->extconn.cs.controller,
2160 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002161 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2162 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2163 }
2164
Mingming Yin3a941d42016-02-17 18:08:05 -08002165
2166 // check sample rate caps
2167 i = 0;
2168 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002169 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2170 out->extconn.cs.controller,
2171 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002172 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2173 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2174 }
2175 }
2176
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002177 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178}
2179
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002180static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2181 uint32_t *supported_sample_rates __unused,
2182 uint32_t max_rates __unused)
2183{
2184 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2185 supported_sample_rates,
2186 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302187 ssize_t i = 0;
2188
2189 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002190 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2191 supported_sample_rates[i]);
2192 }
2193 return count;
2194}
2195
2196static inline int read_usb_sup_channel_masks(bool is_playback,
2197 audio_channel_mask_t *supported_channel_masks,
2198 uint32_t max_masks)
2199{
2200 int channels = audio_extn_usb_get_max_channels(is_playback);
2201 int channel_count;
2202 uint32_t num_masks = 0;
2203 if (channels > MAX_HIFI_CHANNEL_COUNT)
2204 channels = MAX_HIFI_CHANNEL_COUNT;
2205
2206 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002207 // start from 2 channels as framework currently doesn't support mono.
2208 if (channels >= FCC_2) {
2209 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2210 }
2211 for (channel_count = FCC_2;
2212 channel_count <= channels && num_masks < max_masks;
2213 ++channel_count) {
2214 supported_channel_masks[num_masks++] =
2215 audio_channel_mask_for_index_assignment_from_count(channel_count);
2216 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002217 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002218 // For capture we report all supported channel masks from 1 channel up.
2219 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002220 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2221 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002222 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2223 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2224 if (channel_count <= FCC_2) {
2225 mask = audio_channel_in_mask_from_count(channel_count);
2226 supported_channel_masks[num_masks++] = mask;
2227 }
2228 const audio_channel_mask_t index_mask =
2229 audio_channel_mask_for_index_assignment_from_count(channel_count);
2230 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2231 supported_channel_masks[num_masks++] = index_mask;
2232 }
2233 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002234 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302235
vincenttewf51c94e2019-05-07 10:28:53 +08002236 for (size_t i = 0; i < num_masks; ++i) {
2237 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2238 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302239 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002240 return num_masks;
2241}
2242
2243static inline int read_usb_sup_formats(bool is_playback __unused,
2244 audio_format_t *supported_formats,
2245 uint32_t max_formats __unused)
2246{
2247 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2248 switch (bitwidth) {
2249 case 24:
2250 // XXX : usb.c returns 24 for s24 and s24_le?
2251 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2252 break;
2253 case 32:
2254 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2255 break;
2256 case 16:
2257 default :
2258 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2259 break;
2260 }
2261 ALOGV("%s: %s supported format %d", __func__,
2262 is_playback ? "P" : "C", bitwidth);
2263 return 1;
2264}
2265
2266static inline int read_usb_sup_params_and_compare(bool is_playback,
2267 audio_format_t *format,
2268 audio_format_t *supported_formats,
2269 uint32_t max_formats,
2270 audio_channel_mask_t *mask,
2271 audio_channel_mask_t *supported_channel_masks,
2272 uint32_t max_masks,
2273 uint32_t *rate,
2274 uint32_t *supported_sample_rates,
2275 uint32_t max_rates) {
2276 int ret = 0;
2277 int num_formats;
2278 int num_masks;
2279 int num_rates;
2280 int i;
2281
2282 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2283 max_formats);
2284 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2285 max_masks);
2286
2287 num_rates = read_usb_sup_sample_rates(is_playback,
2288 supported_sample_rates, max_rates);
2289
2290#define LUT(table, len, what, dflt) \
2291 for (i=0; i<len && (table[i] != what); i++); \
2292 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2293
2294 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2295 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2296 LUT(supported_sample_rates, num_rates, *rate, 0);
2297
2298#undef LUT
2299 return ret < 0 ? -EINVAL : 0; // HACK TBD
2300}
2301
Alexy Josephb1379942016-01-29 15:49:38 -08002302audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002303 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002304{
2305 struct audio_usecase *usecase;
2306 struct listnode *node;
2307
2308 list_for_each(node, &adev->usecase_list) {
2309 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002310 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002311 ALOGV("%s: usecase id %d", __func__, usecase->id);
2312 return usecase->id;
2313 }
2314 }
2315 return USECASE_INVALID;
2316}
2317
Alexy Josephb1379942016-01-29 15:49:38 -08002318struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002319 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002320{
2321 struct audio_usecase *usecase;
2322 struct listnode *node;
2323
2324 list_for_each(node, &adev->usecase_list) {
2325 usecase = node_to_item(node, struct audio_usecase, list);
2326 if (usecase->id == uc_id)
2327 return usecase;
2328 }
2329 return NULL;
2330}
2331
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302332/*
2333 * is a true native playback active
2334 */
2335bool audio_is_true_native_stream_active(struct audio_device *adev)
2336{
2337 bool active = false;
2338 int i = 0;
2339 struct listnode *node;
2340
2341 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2342 ALOGV("%s:napb: not in true mode or non hdphones device",
2343 __func__);
2344 active = false;
2345 goto exit;
2346 }
2347
2348 list_for_each(node, &adev->usecase_list) {
2349 struct audio_usecase *uc;
2350 uc = node_to_item(node, struct audio_usecase, list);
2351 struct stream_out *curr_out =
2352 (struct stream_out*) uc->stream.out;
2353
2354 if (curr_out && PCM_PLAYBACK == uc->type) {
2355 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2356 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2357 uc->id, curr_out->sample_rate,
2358 curr_out->bit_width,
2359 platform_get_snd_device_name(uc->out_snd_device));
2360
2361 if (is_offload_usecase(uc->id) &&
2362 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2363 active = true;
2364 ALOGD("%s:napb:native stream detected", __func__);
2365 }
2366 }
2367 }
2368exit:
2369 return active;
2370}
2371
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002372uint32_t adev_get_dsp_bit_width_enforce_mode()
2373{
2374 if (adev == NULL) {
2375 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2376 return 0;
2377 }
2378 return adev->dsp_bit_width_enforce_mode;
2379}
2380
2381static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2382{
2383 char value[PROPERTY_VALUE_MAX];
2384 int trial;
2385 uint32_t dsp_bit_width_enforce_mode = 0;
2386
2387 if (!mixer) {
2388 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2389 __func__);
2390 return 0;
2391 }
2392
2393 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2394 value, NULL) > 0) {
2395 trial = atoi(value);
2396 switch (trial) {
2397 case 16:
2398 dsp_bit_width_enforce_mode = 16;
2399 break;
2400 case 24:
2401 dsp_bit_width_enforce_mode = 24;
2402 break;
2403 case 32:
2404 dsp_bit_width_enforce_mode = 32;
2405 break;
2406 default:
2407 dsp_bit_width_enforce_mode = 0;
2408 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2409 break;
2410 }
2411 }
2412
2413 return dsp_bit_width_enforce_mode;
2414}
2415
2416static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2417 uint32_t enforce_mode,
2418 bool enable)
2419{
2420 struct mixer_ctl *ctl = NULL;
2421 const char *mixer_ctl_name = "ASM Bit Width";
2422 uint32_t asm_bit_width_mode = 0;
2423
2424 if (enforce_mode == 0) {
2425 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2426 return;
2427 }
2428
2429 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2430 if (!ctl) {
2431 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2432 __func__, mixer_ctl_name);
2433 return;
2434 }
2435
2436 if (enable)
2437 asm_bit_width_mode = enforce_mode;
2438 else
2439 asm_bit_width_mode = 0;
2440
2441 ALOGV("%s DSP bit width feature status is %d width=%d",
2442 __func__, enable, asm_bit_width_mode);
2443 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2444 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2445 asm_bit_width_mode);
2446
2447 return;
2448}
2449
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302450/*
2451 * if native DSD playback active
2452 */
2453bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2454{
2455 bool active = false;
2456 struct listnode *node = NULL;
2457 struct audio_usecase *uc = NULL;
2458 struct stream_out *curr_out = NULL;
2459
2460 list_for_each(node, &adev->usecase_list) {
2461 uc = node_to_item(node, struct audio_usecase, list);
2462 curr_out = (struct stream_out*) uc->stream.out;
2463
2464 if (curr_out && PCM_PLAYBACK == uc->type &&
2465 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2466 active = true;
2467 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302468 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302469 }
2470 }
2471 return active;
2472}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302473
2474static bool force_device_switch(struct audio_usecase *usecase)
2475{
2476 bool ret = false;
2477 bool is_it_true_mode = false;
2478
Zhou Song30f2c3e2018-02-08 14:02:15 +08002479 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302480 usecase->type == TRANSCODE_LOOPBACK_RX ||
2481 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002482 return false;
2483 }
2484
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002485 if(usecase->stream.out == NULL) {
2486 ALOGE("%s: stream.out is NULL", __func__);
2487 return false;
2488 }
2489
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302490 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002491 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002492 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2493 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302494 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2495 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2496 (!is_it_true_mode && adev->native_playback_enabled)){
2497 ret = true;
2498 ALOGD("napb: time to toggle native mode");
2499 }
2500 }
2501
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302502 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302503 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2504 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002505 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302506 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302507 ALOGD("Force a2dp device switch to update new encoder config");
2508 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002509 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302510
Florian Pfister1a84f312018-07-19 14:38:18 +02002511 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302512 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2513 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002514 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302515 return ret;
2516}
2517
Aalique Grahame22e49102018-12-18 14:23:57 -08002518static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2519{
2520 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2521}
2522
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302523bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2524{
2525 bool ret=false;
2526 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002527 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2528 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302529 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2530 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002531 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302532 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002533 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2534 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302535 ret = true;
2536
2537 return ret;
2538}
2539
2540bool is_a2dp_device(snd_device_t out_snd_device)
2541{
2542 bool ret=false;
2543 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2544 ret = true;
2545
2546 return ret;
2547}
2548
2549bool is_bt_soc_on(struct audio_device *adev)
2550{
2551 struct mixer_ctl *ctl;
2552 char *mixer_ctl_name = "BT SOC status";
2553 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2554 bool bt_soc_status = true;
2555 if (!ctl) {
2556 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2557 __func__, mixer_ctl_name);
2558 /*This is to ensure we dont break targets which dont have the kernel change*/
2559 return true;
2560 }
2561 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2562 ALOGD("BT SOC status: %d",bt_soc_status);
2563 return bt_soc_status;
2564}
2565
Zhou Song331c8e52019-08-26 14:16:12 +08002566static int configure_btsco_sample_rate(snd_device_t snd_device)
2567{
2568 struct mixer_ctl *ctl = NULL;
2569 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2570 char *rate_str = NULL;
2571 bool is_rx_dev = true;
2572
2573 if (is_btsco_device(snd_device, snd_device)) {
2574 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2575 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2576 if (!ctl_sr_tx || !ctl_sr_rx) {
2577 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2578 if (!ctl_sr)
2579 return -ENOSYS;
2580 }
2581
2582 switch (snd_device) {
2583 case SND_DEVICE_OUT_BT_SCO:
2584 rate_str = "KHZ_8";
2585 break;
2586 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2587 case SND_DEVICE_IN_BT_SCO_MIC:
2588 rate_str = "KHZ_8";
2589 is_rx_dev = false;
2590 break;
2591 case SND_DEVICE_OUT_BT_SCO_WB:
2592 rate_str = "KHZ_16";
2593 break;
2594 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2595 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2596 rate_str = "KHZ_16";
2597 is_rx_dev = false;
2598 break;
2599 default:
2600 return 0;
2601 }
2602
2603 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2604 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2605 return -ENOSYS;
2606 }
2607 return 0;
2608}
2609
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302610int out_standby_l(struct audio_stream *stream);
2611
Eric Laurent637e2d42018-11-15 12:24:31 -08002612struct stream_in *adev_get_active_input(const struct audio_device *adev)
2613{
2614 struct listnode *node;
2615 struct stream_in *last_active_in = NULL;
2616
2617 /* Get last added active input.
2618 * TODO: We may use a priority mechanism to pick highest priority active source */
2619 list_for_each(node, &adev->usecase_list)
2620 {
2621 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2622 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2623 last_active_in = usecase->stream.in;
2624 }
2625
2626 return last_active_in;
2627}
2628
2629struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2630{
2631 struct listnode *node;
2632
2633 /* First check active inputs with voice communication source and then
2634 * any input if audio mode is in communication */
2635 list_for_each(node, &adev->usecase_list)
2636 {
2637 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2638 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2639 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2640 return usecase->stream.in;
2641 }
2642 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2643 return adev_get_active_input(adev);
2644
2645 return NULL;
2646}
2647
Carter Hsu2e429db2019-05-14 18:50:52 +08002648/*
2649 * Aligned with policy.h
2650 */
2651static inline int source_priority(int inputSource)
2652{
2653 switch (inputSource) {
2654 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2655 return 9;
2656 case AUDIO_SOURCE_CAMCORDER:
2657 return 8;
2658 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2659 return 7;
2660 case AUDIO_SOURCE_UNPROCESSED:
2661 return 6;
2662 case AUDIO_SOURCE_MIC:
2663 return 5;
2664 case AUDIO_SOURCE_ECHO_REFERENCE:
2665 return 4;
2666 case AUDIO_SOURCE_FM_TUNER:
2667 return 3;
2668 case AUDIO_SOURCE_VOICE_RECOGNITION:
2669 return 2;
2670 case AUDIO_SOURCE_HOTWORD:
2671 return 1;
2672 default:
2673 break;
2674 }
2675 return 0;
2676}
2677
2678static struct stream_in *get_priority_input(struct audio_device *adev)
2679{
2680 struct listnode *node;
2681 struct audio_usecase *usecase;
2682 int last_priority = 0, priority;
2683 struct stream_in *priority_in = NULL;
2684 struct stream_in *in;
2685
2686 list_for_each(node, &adev->usecase_list) {
2687 usecase = node_to_item(node, struct audio_usecase, list);
2688 if (usecase->type == PCM_CAPTURE) {
2689 in = usecase->stream.in;
2690 if (!in)
2691 continue;
2692 priority = source_priority(in->source);
2693
2694 if (priority > last_priority) {
2695 last_priority = priority;
2696 priority_in = in;
2697 }
2698 }
2699 }
2700 return priority_in;
2701}
2702
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002703int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002705 snd_device_t out_snd_device = SND_DEVICE_NONE;
2706 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002707 struct audio_usecase *usecase = NULL;
2708 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002709 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002710 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302711 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002712 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002713 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302715 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2716
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002717 usecase = get_usecase_from_list(adev, uc_id);
2718 if (usecase == NULL) {
2719 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2720 return -EINVAL;
2721 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002723 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002724 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002725 (usecase->type == PCM_HFP_CALL)||
2726 (usecase->type == ICC_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302727 if(usecase->stream.out == NULL) {
2728 ALOGE("%s: stream.out is NULL", __func__);
2729 return -EINVAL;
2730 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002731 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002732 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2733 uc_id);
2734 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2735 uc_id);
2736 } else {
2737 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302738 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002739 in_snd_device = platform_get_input_snd_device(adev->platform,
2740 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302741 &usecase->stream.out->device_list,
2742 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002743 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002744 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302745 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302746 if (usecase->stream.inout == NULL) {
2747 ALOGE("%s: stream.inout is NULL", __func__);
2748 return -EINVAL;
2749 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002750 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302751 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2752 stream_out.format = usecase->stream.inout->out_config.format;
2753 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302754 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002755 assign_devices(&usecase->device_list,
2756 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302757 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2758 if (usecase->stream.inout == NULL) {
2759 ALOGE("%s: stream.inout is NULL", __func__);
2760 return -EINVAL;
2761 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302762 struct listnode out_devices;
2763 list_init(&out_devices);
2764 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2765 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002766 assign_devices(&usecase->device_list,
2767 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002768 } else {
2769 /*
2770 * If the voice call is active, use the sound devices of voice call usecase
2771 * so that it would not result any device switch. All the usecases will
2772 * be switched to new device when select_devices() is called for voice call
2773 * usecase. This is to avoid switching devices for voice call when
2774 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002775 * choose voice call device only if the use case device is
2776 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002777 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002778 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002779 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002780 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002781 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2782 is_codec_backend_out_device_type(&usecase->device_list)) ||
2783 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2784 is_codec_backend_in_device_type(&usecase->device_list)) ||
2785 is_single_device_type_equal(&vc_usecase->device_list,
2786 AUDIO_DEVICE_OUT_HEARING_AID) ||
2787 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002788 AUDIO_DEVICE_IN_VOICE_CALL) ||
2789 (is_single_device_type_equal(&usecase->device_list,
2790 AUDIO_DEVICE_IN_USB_HEADSET) &&
2791 is_single_device_type_equal(&vc_usecase->device_list,
2792 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002793 in_snd_device = vc_usecase->in_snd_device;
2794 out_snd_device = vc_usecase->out_snd_device;
2795 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002796 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002797 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002798 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002799 if ((voip_usecase != NULL) &&
2800 (usecase->type == PCM_PLAYBACK) &&
2801 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002802 out_snd_device_backend_match = platform_check_backends_match(
2803 voip_usecase->out_snd_device,
2804 platform_get_output_snd_device(
2805 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302806 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002807 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002808 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2809 (is_codec_backend_out_device_type(&usecase->device_list) ||
2810 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002811 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002812 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002813 in_snd_device = voip_usecase->in_snd_device;
2814 out_snd_device = voip_usecase->out_snd_device;
2815 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002816 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002817 hfp_ucid = audio_extn_hfp_get_usecase();
2818 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002819 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002820 in_snd_device = hfp_usecase->in_snd_device;
2821 out_snd_device = hfp_usecase->out_snd_device;
2822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002823 }
2824 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302825 if (usecase->stream.out == NULL) {
2826 ALOGE("%s: stream.out is NULL", __func__);
2827 return -EINVAL;
2828 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002829 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002830 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002831 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002832 struct stream_out *voip_out = adev->primary_output;
2833 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002834 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002835 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2836 else
2837 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302838 usecase->stream.out,
2839 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002840 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002841
Eric Laurent637e2d42018-11-15 12:24:31 -08002842 if (voip_usecase)
2843 voip_out = voip_usecase->stream.out;
2844
2845 if (usecase->stream.out == voip_out && voip_in != NULL)
2846 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002847 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002848 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302849 if (usecase->stream.in == NULL) {
2850 ALOGE("%s: stream.in is NULL", __func__);
2851 return -EINVAL;
2852 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002853 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002854 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002855 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002856 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002857 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002858 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002859
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002860 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002861 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002862 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2863 USECASE_AUDIO_PLAYBACK_VOIP);
2864
Carter Hsu2e429db2019-05-14 18:50:52 +08002865 usecase->stream.in->enable_ec_port = false;
2866
Zhou Song62ea0282020-03-22 19:53:01 +08002867 bool is_ha_usecase = adev->ha_proxy_enable ?
2868 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2869 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2870 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002871 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002872 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002873 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002874 } else if (adev->primary_output &&
2875 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002876 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002877 } else {
2878 /* forcing speaker o/p device to get matching i/p pair
2879 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002880 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002881 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002882 priority_in = voip_in;
2883 } else {
2884 /* get the input with the highest priority source*/
2885 priority_in = get_priority_input(adev);
2886
2887 if (!priority_in)
2888 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002889 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002890 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2891 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2892 }
2893 else
2894 in_snd_device = platform_get_input_snd_device(adev->platform,
2895 priority_in,
2896 &out_devices,
2897 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002898 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002899 }
2900 }
2901
2902 if (out_snd_device == usecase->out_snd_device &&
2903 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302904
2905 if (!force_device_switch(usecase))
2906 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 }
2908
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002909 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002910 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002911 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002912 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2913 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302914 }
2915
Aalique Grahame22e49102018-12-18 14:23:57 -08002916 if (out_snd_device != SND_DEVICE_NONE &&
2917 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2918 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2919 __func__,
2920 use_case_table[uc_id],
2921 adev->last_logged_snd_device[uc_id][0],
2922 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2923 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2924 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2925 -1,
2926 out_snd_device,
2927 platform_get_snd_device_name(out_snd_device),
2928 platform_get_snd_device_acdb_id(out_snd_device));
2929 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2930 }
2931 if (in_snd_device != SND_DEVICE_NONE &&
2932 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2933 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2934 __func__,
2935 use_case_table[uc_id],
2936 adev->last_logged_snd_device[uc_id][1],
2937 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2938 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2939 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2940 -1,
2941 in_snd_device,
2942 platform_get_snd_device_name(in_snd_device),
2943 platform_get_snd_device_acdb_id(in_snd_device));
2944 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2945 }
2946
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 /*
2949 * Limitation: While in call, to do a device switch we need to disable
2950 * and enable both RX and TX devices though one of them is same as current
2951 * device.
2952 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002953 if ((usecase->type == VOICE_CALL) &&
2954 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2955 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002956 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002957 }
2958
2959 if (((usecase->type == VOICE_CALL) ||
2960 (usecase->type == VOIP_CALL)) &&
2961 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2962 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302963 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002964 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002965 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002966
2967 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302968 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002969 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002970 }
2971
Aalique Grahame22e49102018-12-18 14:23:57 -08002972 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2973 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002974 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302975 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002976 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2977 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2978 else
2979 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302980 }
2981
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002982 /* Disable current sound devices */
2983 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002984 disable_audio_route(adev, usecase);
2985 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 }
2987
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002988 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002989 disable_audio_route(adev, usecase);
2990 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 }
2992
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002993 /* Applicable only on the targets that has external modem.
2994 * New device information should be sent to modem before enabling
2995 * the devices to reduce in-call device switch time.
2996 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002997 if ((usecase->type == VOICE_CALL) &&
2998 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2999 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003000 status = platform_switch_voice_call_enable_device_config(adev->platform,
3001 out_snd_device,
3002 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003003 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003004
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003005 /* Enable new sound devices */
3006 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003007 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303008 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303009 if (platform_check_codec_asrc_support(adev->platform))
3010 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003011 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003012 /* Enable haptics device for haptic usecase */
3013 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3014 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 }
3016
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003017 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303018 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003019 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003020 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003021
Avinash Vaish71a8b972014-07-24 15:36:33 +05303022 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003023 status = platform_switch_voice_call_device_post(adev->platform,
3024 out_snd_device,
3025 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05303026 enable_audio_route_for_voice_usecases(adev, usecase);
3027 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003028
sangwoo170731f2013-06-08 15:36:36 +09003029 usecase->in_snd_device = in_snd_device;
3030 usecase->out_snd_device = out_snd_device;
3031
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303032 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3033 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303034 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003035 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003036 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003037 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3038 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3039 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3040 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3041 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3042 /*
3043 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3044 * configured device sample rate, if not update the COPP rate to be equal to the
3045 * device sample rate, else open COPP at stream sample rate
3046 */
3047 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3048 usecase->stream.out->sample_rate,
3049 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303050 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303051 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3052 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303053 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003054 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3055 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3056 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3057 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003058 }
3059 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003060
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003061 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003062
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003063 /* If input stream is already running then effect needs to be
3064 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003065 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003066 check_and_enable_effect(adev);
3067
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003068 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003069 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303070 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003071 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3072
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003073 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303074 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003075 voice_extn_compress_voip_is_started(adev))
3076 voice_set_sidetone(adev, out_snd_device, true);
3077 }
3078
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003079 /* Applicable only on the targets that has external modem.
3080 * Enable device command should be sent to modem only after
3081 * enabling voice call mixer controls
3082 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003083 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003084 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3085 out_snd_device,
3086 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303087
3088 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003089 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303090 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003091 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303092 if (is_bt_soc_on(adev) == false){
3093 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003094 if (in->pcm != NULL)
3095 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303096 }
3097 }
3098 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3099 && usecase->stream.out->started) {
3100 if (is_bt_soc_on(adev) == false) {
3101 ALOGD("BT SCO/A2DP disconnected while in connection");
3102 out_standby_l(&usecase->stream.out->stream.common);
3103 }
3104 }
3105 } else if ((usecase->stream.out != NULL) &&
3106 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303107 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3108 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003109 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303110 usecase->stream.out->started) {
3111 if (is_bt_soc_on(adev) == false) {
3112 ALOGD("BT SCO/A2dp disconnected while in connection");
3113 out_standby_l(&usecase->stream.out->stream.common);
3114 }
3115 }
3116 }
3117
Yung Ti Su70cb8242018-06-22 17:38:47 +08003118 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003119 struct stream_out *voip_out = voip_usecase->stream.out;
3120 audio_extn_utils_send_app_type_gain(adev,
3121 voip_out->app_type_cfg.app_type,
3122 &voip_out->app_type_cfg.gain[0]);
3123 }
3124
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003125 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 return status;
3128}
3129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130static int stop_input_stream(struct stream_in *in)
3131{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303132 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303134
3135 if (in == NULL) {
3136 ALOGE("%s: stream_in ptr is NULL", __func__);
3137 return -EINVAL;
3138 }
3139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003141 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142
Eric Laurent994a6932013-07-17 11:51:42 -07003143 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003144 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 uc_info = get_usecase_from_list(adev, in->usecase);
3146 if (uc_info == NULL) {
3147 ALOGE("%s: Could not find the usecase (%d) in the list",
3148 __func__, in->usecase);
3149 return -EINVAL;
3150 }
3151
Carter Hsu2e429db2019-05-14 18:50:52 +08003152 priority_in = get_priority_input(adev);
3153
Derek Chenea197282019-01-07 17:35:01 -08003154 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3155 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003156
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003157 /* Close in-call recording streams */
3158 voice_check_and_stop_incall_rec_usecase(adev, in);
3159
Eric Laurent150dbfe2013-02-27 14:31:02 -08003160 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003161 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003162
3163 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003164 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003166 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303167 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3168
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003169 list_remove(&uc_info->list);
3170 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171
Carter Hsu2e429db2019-05-14 18:50:52 +08003172 if (priority_in == in) {
3173 priority_in = get_priority_input(adev);
3174 if (priority_in)
3175 select_devices(adev, priority_in->usecase);
3176 }
3177
Vatsal Buchac09ae062018-11-14 13:25:08 +05303178 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003179 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 return ret;
3181}
3182
3183int start_input_stream(struct stream_in *in)
3184{
3185 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003186 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303188
3189 if (in == NULL) {
3190 ALOGE("%s: stream_in ptr is NULL", __func__);
3191 return -EINVAL;
3192 }
3193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003195 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003196 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197
Mingming Yin2664a5b2015-09-03 10:53:11 -07003198 if (get_usecase_from_list(adev, usecase) == NULL)
3199 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303200 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3201 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003202
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303203 if (CARD_STATUS_OFFLINE == in->card_status||
3204 CARD_STATUS_OFFLINE == adev->card_status) {
3205 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303206 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303207 goto error_config;
3208 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303209
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003210 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303211 if (!adev->bt_sco_on) {
3212 ALOGE("%s: SCO profile is not ready, return error", __func__);
3213 ret = -EIO;
3214 goto error_config;
3215 }
3216 }
3217
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003218 /* Check if source matches incall recording usecase criteria */
3219 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3220 if (ret)
3221 goto error_config;
3222 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003223 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3224
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303225 if (audio_extn_cin_attached_usecase(in))
3226 audio_extn_cin_acquire_usecase(in);
3227
Mingming Yin2664a5b2015-09-03 10:53:11 -07003228 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3229 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3230 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003231 ret = -EINVAL;
3232 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003233 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003234
Eric Laurentb23d5282013-05-14 15:27:20 -07003235 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 if (in->pcm_device_id < 0) {
3237 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3238 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003239 ret = -EINVAL;
3240 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003244
3245 if (!uc_info) {
3246 ret = -ENOMEM;
3247 goto error_config;
3248 }
3249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 uc_info->id = in->usecase;
3251 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003252 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003253 list_init(&uc_info->device_list);
3254 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003255 uc_info->in_snd_device = SND_DEVICE_NONE;
3256 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003258 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003259 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303260 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3261 adev->perf_lock_opts,
3262 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003263 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264
Derek Chenea197282019-01-07 17:35:01 -08003265 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3266 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003267
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303268 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3269
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303270 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303271 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303272 if (ret)
3273 goto error_open;
3274 else
3275 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003276 }
3277
Haynes Mathew George16081042017-05-31 17:16:49 -07003278 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003279 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003280 ALOGE("%s: pcm stream not ready", __func__);
3281 goto error_open;
3282 }
3283 ret = pcm_start(in->pcm);
3284 if (ret < 0) {
3285 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3286 goto error_open;
3287 }
3288 } else {
3289 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3290 unsigned int pcm_open_retry_count = 0;
3291
Zhou Song62ea0282020-03-22 19:53:01 +08003292 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3293 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003294 flags |= PCM_MMAP | PCM_NOIRQ;
3295 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3296 } else if (in->realtime) {
3297 flags |= PCM_MMAP | PCM_NOIRQ;
3298 }
3299
Garmond Leunge2433c32017-09-28 21:51:22 -07003300 if (audio_extn_ffv_get_stream() == in) {
3301 ALOGD("%s: ffv stream, update pcm config", __func__);
3302 audio_extn_ffv_update_pcm_config(&config);
3303 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003304 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3305 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3306
3307 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003308 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003309 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003310 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003311 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303312 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303313 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3314 adev->card_status = CARD_STATUS_OFFLINE;
3315 in->card_status = CARD_STATUS_OFFLINE;
3316 ret = -EIO;
3317 goto error_open;
3318 }
3319
Haynes Mathew George16081042017-05-31 17:16:49 -07003320 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3321 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3322 if (in->pcm != NULL) {
3323 pcm_close(in->pcm);
3324 in->pcm = NULL;
3325 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003326 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003327 ret = -EIO;
3328 goto error_open;
3329 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003330 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003331 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3332 continue;
3333 }
3334 break;
3335 }
3336
3337 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003338 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003339 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003340 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003341 if (ret < 0) {
3342 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3343 pcm_close(in->pcm);
3344 in->pcm = NULL;
3345 goto error_open;
3346 }
3347 register_in_stream(in);
3348 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003349 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003350 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003351 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003352 if (ret < 0) {
3353 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003354 pcm_close(in->pcm);
3355 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003356 goto error_open;
3357 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003358 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003359 }
3360
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003361 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003362 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3363 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003364
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003365 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303366 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3367
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303368done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003369 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303370 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303371 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303372 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003373 return ret;
3374
3375error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003376 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303377 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003379
Eric Laurentc8400632013-02-14 19:04:54 -08003380error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003381 if (audio_extn_cin_attached_usecase(in))
3382 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303383 /*
3384 * sleep 50ms to allow sufficient time for kernel
3385 * drivers to recover incases like SSR.
3386 */
3387 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003388 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303389 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003390 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391}
3392
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003393void lock_input_stream(struct stream_in *in)
3394{
3395 pthread_mutex_lock(&in->pre_lock);
3396 pthread_mutex_lock(&in->lock);
3397 pthread_mutex_unlock(&in->pre_lock);
3398}
3399
3400void lock_output_stream(struct stream_out *out)
3401{
3402 pthread_mutex_lock(&out->pre_lock);
3403 pthread_mutex_lock(&out->lock);
3404 pthread_mutex_unlock(&out->pre_lock);
3405}
3406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003407/* must be called with out->lock locked */
3408static int send_offload_cmd_l(struct stream_out* out, int command)
3409{
3410 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3411
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003412 if (!cmd) {
3413 ALOGE("failed to allocate mem for command 0x%x", command);
3414 return -ENOMEM;
3415 }
3416
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003417 ALOGVV("%s %d", __func__, command);
3418
3419 cmd->cmd = command;
3420 list_add_tail(&out->offload_cmd_list, &cmd->node);
3421 pthread_cond_signal(&out->offload_cond);
3422 return 0;
3423}
3424
Weiyin Jiang280ea742020-09-08 20:28:22 +08003425/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426static void stop_compressed_output_l(struct stream_out *out)
3427{
3428 out->offload_state = OFFLOAD_STATE_IDLE;
3429 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003430 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 if (out->compr != NULL) {
3432 compress_stop(out->compr);
3433 while (out->offload_thread_blocked) {
3434 pthread_cond_wait(&out->cond, &out->lock);
3435 }
3436 }
3437}
3438
Varun Balaraje49253e2017-07-06 19:48:56 +05303439bool is_interactive_usecase(audio_usecase_t uc_id)
3440{
3441 unsigned int i;
3442 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3443 if (uc_id == interactive_usecases[i])
3444 return true;
3445 }
3446 return false;
3447}
3448
3449static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3450{
3451 audio_usecase_t ret_uc = USECASE_INVALID;
3452 unsigned int intract_uc_index;
3453 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3454
3455 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3456 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3457 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3458 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3459 ret_uc = interactive_usecases[intract_uc_index];
3460 break;
3461 }
3462 }
3463
3464 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3465 return ret_uc;
3466}
3467
3468static void free_interactive_usecase(struct audio_device *adev,
3469 audio_usecase_t uc_id)
3470{
3471 unsigned int interact_uc_index;
3472 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3473
3474 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3475 if (interactive_usecases[interact_uc_index] == uc_id) {
3476 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3477 break;
3478 }
3479 }
3480 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3481}
3482
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003483bool is_offload_usecase(audio_usecase_t uc_id)
3484{
3485 unsigned int i;
3486 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3487 if (uc_id == offload_usecases[i])
3488 return true;
3489 }
3490 return false;
3491}
3492
Dhananjay Kumarac341582017-02-23 23:42:25 +05303493static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003494{
vivek mehta446c3962015-09-14 10:57:35 -07003495 audio_usecase_t ret_uc = USECASE_INVALID;
3496 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003497 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003498 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303499 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003500 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3501 else
3502 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003503
vivek mehta446c3962015-09-14 10:57:35 -07003504 pthread_mutex_lock(&adev->lock);
3505 if (get_usecase_from_list(adev, ret_uc) != NULL)
3506 ret_uc = USECASE_INVALID;
3507 pthread_mutex_unlock(&adev->lock);
3508
3509 return ret_uc;
3510 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003511
3512 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003513 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3514 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3515 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3516 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003517 break;
3518 }
3519 }
vivek mehta446c3962015-09-14 10:57:35 -07003520
3521 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3522 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003523}
3524
3525static void free_offload_usecase(struct audio_device *adev,
3526 audio_usecase_t uc_id)
3527{
vivek mehta446c3962015-09-14 10:57:35 -07003528 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003529 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003530
3531 if (!adev->multi_offload_enable)
3532 return;
3533
3534 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3535 if (offload_usecases[offload_uc_index] == uc_id) {
3536 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003537 break;
3538 }
3539 }
3540 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3541}
3542
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543static void *offload_thread_loop(void *context)
3544{
3545 struct stream_out *out = (struct stream_out *) context;
3546 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003547 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003550 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3552
3553 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003554 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003555 out->offload_state = OFFLOAD_STATE_IDLE;
3556 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 for (;;) {
3558 struct offload_cmd *cmd = NULL;
3559 stream_callback_event_t event;
3560 bool send_callback = false;
3561
3562 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3563 __func__, list_empty(&out->offload_cmd_list),
3564 out->offload_state);
3565 if (list_empty(&out->offload_cmd_list)) {
3566 ALOGV("%s SLEEPING", __func__);
3567 pthread_cond_wait(&out->offload_cond, &out->lock);
3568 ALOGV("%s RUNNING", __func__);
3569 continue;
3570 }
3571
3572 item = list_head(&out->offload_cmd_list);
3573 cmd = node_to_item(item, struct offload_cmd, node);
3574 list_remove(item);
3575
3576 ALOGVV("%s STATE %d CMD %d out->compr %p",
3577 __func__, out->offload_state, cmd->cmd, out->compr);
3578
3579 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3580 free(cmd);
3581 break;
3582 }
3583
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003584 // allow OFFLOAD_CMD_ERROR reporting during standby
3585 // this is needed to handle failures during compress_open
3586 // Note however that on a pause timeout, the stream is closed
3587 // and no offload usecase will be active. Therefore this
3588 // special case is needed for compress_open failures alone
3589 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3590 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003591 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003592 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 pthread_cond_signal(&out->cond);
3594 continue;
3595 }
3596 out->offload_thread_blocked = true;
3597 pthread_mutex_unlock(&out->lock);
3598 send_callback = false;
3599 switch(cmd->cmd) {
3600 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003601 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003602 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003603 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003604 send_callback = true;
3605 event = STREAM_CBK_EVENT_WRITE_READY;
3606 break;
3607 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003608 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303609 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003610 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303611 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003612 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303613 if (ret < 0)
3614 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303615 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303616 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003617 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003618 else
3619 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003620 if (-ENETRESET != ret && !(-EINTR == ret &&
3621 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303622 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303623 pthread_mutex_lock(&out->lock);
3624 out->send_new_metadata = 1;
3625 out->send_next_track_params = true;
3626 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303627 event = STREAM_CBK_EVENT_DRAIN_READY;
3628 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3629 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303630 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003631 break;
3632 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003633 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003634 ret = compress_drain(out->compr);
3635 ALOGD("copl(%p):out of compress_drain", out);
3636 // EINTR check avoids drain interruption due to SSR
3637 if (-ENETRESET != ret && !(-EINTR == ret &&
3638 CARD_STATUS_OFFLINE == out->card_status)) {
3639 send_callback = true;
3640 event = STREAM_CBK_EVENT_DRAIN_READY;
3641 } else
3642 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003643 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303644 case OFFLOAD_CMD_ERROR:
3645 ALOGD("copl(%p): sending error callback to AF", out);
3646 send_callback = true;
3647 event = STREAM_CBK_EVENT_ERROR;
3648 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003649 default:
3650 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3651 break;
3652 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003653 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 out->offload_thread_blocked = false;
3655 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003656 if (send_callback && out->client_callback) {
3657 ALOGVV("%s: sending client_callback event %d", __func__, event);
3658 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003659 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 free(cmd);
3661 }
3662
3663 pthread_cond_signal(&out->cond);
3664 while (!list_empty(&out->offload_cmd_list)) {
3665 item = list_head(&out->offload_cmd_list);
3666 list_remove(item);
3667 free(node_to_item(item, struct offload_cmd, node));
3668 }
3669 pthread_mutex_unlock(&out->lock);
3670
3671 return NULL;
3672}
3673
3674static int create_offload_callback_thread(struct stream_out *out)
3675{
3676 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3677 list_init(&out->offload_cmd_list);
3678 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3679 offload_thread_loop, out);
3680 return 0;
3681}
3682
3683static int destroy_offload_callback_thread(struct stream_out *out)
3684{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003685 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08003686 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687 stop_compressed_output_l(out);
3688 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3689
Weiyin Jiang280ea742020-09-08 20:28:22 +08003690 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 pthread_mutex_unlock(&out->lock);
3692 pthread_join(out->offload_thread, (void **) NULL);
3693 pthread_cond_destroy(&out->offload_cond);
3694
3695 return 0;
3696}
3697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698static int stop_output_stream(struct stream_out *out)
3699{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 struct audio_usecase *uc_info;
3702 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003703 bool has_voip_usecase =
3704 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705
Eric Laurent994a6932013-07-17 11:51:42 -07003706 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003707 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 uc_info = get_usecase_from_list(adev, out->usecase);
3709 if (uc_info == NULL) {
3710 ALOGE("%s: Could not find the usecase (%d) in the list",
3711 __func__, out->usecase);
3712 return -EINVAL;
3713 }
3714
Derek Chenea197282019-01-07 17:35:01 -08003715 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3716 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003717
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003718 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303719 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003720 if (adev->visualizer_stop_output != NULL)
3721 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003722
3723 audio_extn_dts_remove_state_notifier_node(out->usecase);
3724
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003725 if (adev->offload_effects_stop_output != NULL)
3726 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003727 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3728 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3729 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003730 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003731
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003732 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3733 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003734 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003735 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003736
Eric Laurent150dbfe2013-02-27 14:31:02 -08003737 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003738 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003739
3740 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003741 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003742 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3743 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744
Aalique Grahame22e49102018-12-18 14:23:57 -08003745 audio_extn_extspk_update(adev->extspk);
3746
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003747 if (is_offload_usecase(out->usecase)) {
3748 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3749 adev->dsp_bit_width_enforce_mode,
3750 false);
3751 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003752 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003753 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3754 false);
3755
3756 if (ret != 0)
3757 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3758 /* default service interval was successfully updated,
3759 reopen USB backend with new service interval */
3760 ret = 0;
3761 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003762
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003763 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303764 out->started = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08003765 pthread_mutex_lock(&out->latch_lock);
3766 out->muted = false;
3767 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003768 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303769 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003770 ALOGV("Disable passthrough , reset mixer to pcm");
3771 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003772#ifdef AUDIO_GKI_ENABLED
3773 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3774 out->compr_config.codec->reserved[0] = 0;
3775#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003776 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003777#endif
Mingming Yin21854652016-04-13 11:54:02 -07003778 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003779 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3780 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003781
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303782 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003783 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303784 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303785
Manish Dewangan21a850a2017-08-14 12:03:55 +05303786 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003787 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3788 if (ret < 0)
3789 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3790 }
3791
juyuchen2d415992018-11-16 14:15:16 +08003792 /* 1) media + voip output routing to handset must route media back to
3793 speaker when voip stops.
3794 2) trigger voip input to reroute when voip output changes to
3795 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003796 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003797 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003798 struct listnode *node;
3799 struct audio_usecase *usecase;
3800 list_for_each(node, &adev->usecase_list) {
3801 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003802 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303803 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3804 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003805 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003806 continue;
3807
3808 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3809 __func__, usecase->id, use_case_table[usecase->id],
3810 out->usecase, use_case_table[out->usecase]);
3811 select_devices(adev, usecase->id);
3812 }
3813 }
3814
Garmond Leung5fd0b552018-04-17 11:56:12 -07003815 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003816 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 return ret;
3818}
3819
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003820struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3821 unsigned int flags, unsigned int pcm_open_retry_count,
3822 struct pcm_config *config)
3823{
3824 struct pcm* pcm = NULL;
3825
3826 while (1) {
3827 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3828 if (pcm == NULL || !pcm_is_ready(pcm)) {
3829 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3830 if (pcm != NULL) {
3831 pcm_close(pcm);
3832 pcm = NULL;
3833 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003834 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003835 return NULL;
3836
Weiyin Jiang72197252019-10-09 11:49:32 +08003837 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003838 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3839 continue;
3840 }
3841 break;
3842 }
3843
3844 if (pcm_is_ready(pcm)) {
3845 int ret = pcm_prepare(pcm);
3846 if (ret < 0) {
3847 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3848 pcm_close(pcm);
3849 pcm = NULL;
3850 }
3851 }
3852
3853 return pcm;
3854}
3855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856int start_output_stream(struct stream_out *out)
3857{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 struct audio_usecase *uc_info;
3860 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003861 char mixer_ctl_name[128];
3862 struct mixer_ctl *ctl = NULL;
3863 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303864 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003865 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866
Haynes Mathew George380745d2017-10-04 15:27:45 -07003867 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003868 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3869 ret = -EINVAL;
3870 goto error_config;
3871 }
3872
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003873 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303874 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003875 get_device_types(&out->device_list), is_haptic_usecase);
3876
3877 bool is_speaker_active = compare_device_type(&out->device_list,
3878 AUDIO_DEVICE_OUT_SPEAKER);
3879 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3880 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303881
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303882 if (CARD_STATUS_OFFLINE == out->card_status ||
3883 CARD_STATUS_OFFLINE == adev->card_status) {
3884 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303885 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003886 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303887 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303888
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003889 //Update incall music usecase to reflect correct voice session
3890 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3891 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3892 if (ret != 0) {
3893 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3894 __func__, ret);
3895 goto error_config;
3896 }
3897 }
3898
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003899 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003900 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003901 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303902 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303903 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003904 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303905 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3906 ret = -EAGAIN;
3907 goto error_config;
3908 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303909 }
3910 }
3911 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003912 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303913 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003914 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303915 //combo usecase just by pass a2dp
3916 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003917 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303918 } else {
3919 ALOGE("%s: SCO profile is not ready, return error", __func__);
3920 ret = -EAGAIN;
3921 goto error_config;
3922 }
3923 }
3924 }
3925
Eric Laurentb23d5282013-05-14 15:27:20 -07003926 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 if (out->pcm_device_id < 0) {
3928 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3929 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003930 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003931 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932 }
3933
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003934 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003935 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3936 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003937 if (adev->haptic_pcm_device_id < 0) {
3938 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3939 __func__, adev->haptic_pcm_device_id, out->usecase);
3940 ret = -EINVAL;
3941 goto error_config;
3942 }
3943 }
3944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003946
3947 if (!uc_info) {
3948 ret = -ENOMEM;
3949 goto error_config;
3950 }
3951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 uc_info->id = out->usecase;
3953 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003954 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003955 list_init(&uc_info->device_list);
3956 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003957 uc_info->in_snd_device = SND_DEVICE_NONE;
3958 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003959
3960 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003961 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003962 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3963 /* USB backend is not reopened immediately.
3964 This is eventually done as part of select_devices */
3965 }
3966
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003967 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968
Wei Wangf7ca6c92017-11-21 14:51:20 -08003969 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303970 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3971 adev->perf_lock_opts,
3972 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303973
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003974 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303975 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303976 if (audio_extn_passthru_is_enabled() &&
3977 audio_extn_passthru_is_passthrough_stream(out)) {
3978 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303979 }
3980 }
3981
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003982 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003983 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303984 if (!a2dp_combo) {
3985 check_a2dp_restore_l(adev, out, false);
3986 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003987 struct listnode dev;
3988 list_init(&dev);
3989 assign_devices(&dev, &out->device_list);
3990 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3991 reassign_device_list(&out->device_list,
3992 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003993 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003994 reassign_device_list(&out->device_list,
3995 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303996 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003997 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303998 }
3999 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304000 select_devices(adev, out->usecase);
4001 if (is_a2dp_out_device_type(&out->device_list) &&
4002 !adev->a2dp_started) {
4003 if (is_speaker_active || is_speaker_safe_active) {
4004 struct listnode dev;
4005 list_init(&dev);
4006 assign_devices(&dev, &out->device_list);
4007 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4008 reassign_device_list(&out->device_list,
4009 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4010 else
4011 reassign_device_list(&out->device_list,
4012 AUDIO_DEVICE_OUT_SPEAKER, "");
4013 select_devices(adev, out->usecase);
4014 assign_devices(&out->device_list, &dev);
4015 } else {
4016 ret = -EINVAL;
4017 goto error_open;
4018 }
4019 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304020 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004021
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004022 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4023 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004024 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004025 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004026
Derek Chenea197282019-01-07 17:35:01 -08004027 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4028 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004029
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004030 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4031 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004032
4033 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004034 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004035 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4036 ALOGE("%s: pcm stream not ready", __func__);
4037 goto error_open;
4038 }
4039 ret = pcm_start(out->pcm);
4040 if (ret < 0) {
4041 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4042 goto error_open;
4043 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004044 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004045 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004046 unsigned int flags = PCM_OUT;
4047 unsigned int pcm_open_retry_count = 0;
4048 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4049 flags |= PCM_MMAP | PCM_NOIRQ;
4050 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004051 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004052 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004053 } else
4054 flags |= PCM_MONOTONIC;
4055
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004056 if ((adev->vr_audio_mode_enabled) &&
4057 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4058 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4059 "PCM_Dev %d Topology", out->pcm_device_id);
4060 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4061 if (!ctl) {
4062 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4063 __func__, mixer_ctl_name);
4064 } else {
4065 //if success use ULLPP
4066 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4067 __func__, mixer_ctl_name, out->pcm_device_id);
4068 //There is a still a possibility that some sessions
4069 // that request for FAST|RAW when 3D audio is active
4070 //can go through ULLPP. Ideally we expects apps to
4071 //listen to audio focus and stop concurrent playback
4072 //Also, we will look for mode flag (voice_in_communication)
4073 //before enabling the realtime flag.
4074 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4075 }
4076 }
4077
Surendar Karka91fa3682018-07-02 18:12:12 +05304078 if (out->realtime)
4079 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4080 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4081
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004082 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4083 flags, pcm_open_retry_count,
4084 &(out->config));
4085 if (out->pcm == NULL) {
4086 ret = -EIO;
4087 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004088 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004089
4090 if (is_haptic_usecase) {
4091 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4092 adev->haptic_pcm_device_id,
4093 flags, pcm_open_retry_count,
4094 &(adev->haptics_config));
4095 // failure to open haptics pcm shouldnt stop audio,
4096 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004097
4098 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4099 ALOGD("%s: enable haptic audio synchronization", __func__);
4100 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4101 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004102 }
4103
Surendar Karka91fa3682018-07-02 18:12:12 +05304104 if (!out->realtime)
4105 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304106 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004107
Zhou Song2b8f28f2017-09-11 10:51:38 +08004108 // apply volume for voip playback after path is set up
4109 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4110 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304111 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4112 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304113 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4114 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004115 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4116 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304117 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004118 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004119 /*
4120 * set custom channel map if:
4121 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4122 * 2. custom channel map has been set by client
4123 * else default channel map of FC/FR/FL can always be set to DSP
4124 */
4125 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4126 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4127 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004128 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4129 adev->dsp_bit_width_enforce_mode,
4130 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004132 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004133 out->compr = compress_open(adev->snd_card,
4134 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004135 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004136 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304137 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304138 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4139 adev->card_status = CARD_STATUS_OFFLINE;
4140 out->card_status = CARD_STATUS_OFFLINE;
4141 ret = -EIO;
4142 goto error_open;
4143 }
4144
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004145 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004146 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004147 compress_close(out->compr);
4148 out->compr = NULL;
4149 ret = -EIO;
4150 goto error_open;
4151 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304152 /* compress_open sends params of the track, so reset the flag here */
4153 out->is_compr_metadata_avail = false;
4154
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004155 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004156 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004157
Fred Oh3f43e742015-03-04 18:42:34 -08004158 /* Since small bufs uses blocking writes, a write will be blocked
4159 for the default max poll time (20s) in the event of an SSR.
4160 Reduce the poll time to observe and deal with SSR faster.
4161 */
Ashish Jain5106d362016-05-11 19:23:33 +05304162 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004163 compress_set_max_poll_wait(out->compr, 1000);
4164 }
4165
Manish Dewangan69426c82017-01-30 17:35:36 +05304166 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304167 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304168
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004169 audio_extn_dts_create_state_notifier_node(out->usecase);
4170 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4171 popcount(out->channel_mask),
4172 out->playback_started);
4173
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004174#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304175 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004176 audio_extn_dolby_send_ddp_endp_params(adev);
4177#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304178 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4179 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004180 if (adev->visualizer_start_output != NULL)
4181 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4182 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304183 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004184 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004185 }
Derek Chenf13dd492018-11-13 14:53:51 -08004186
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004187 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004188 /* Update cached volume from media to offload/direct stream */
4189 struct listnode *node = NULL;
4190 list_for_each(node, &adev->active_outputs_list) {
4191 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4192 streams_output_ctxt_t,
4193 list);
4194 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4195 out->volume_l = out_ctxt->output->volume_l;
4196 out->volume_r = out_ctxt->output->volume_r;
4197 }
4198 }
4199 out_set_compr_volume(&out->stream,
4200 out->volume_l, out->volume_r);
4201 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004203
4204 if (ret == 0) {
4205 register_out_stream(out);
4206 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004207 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4208 ALOGE("%s: pcm stream not ready", __func__);
4209 goto error_open;
4210 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004211 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004212 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004213 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004214 if (ret < 0)
4215 goto error_open;
4216 }
4217 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004218 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304219 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304220 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004221
vivek mehtad15d2bf2019-05-17 13:35:10 -07004222 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4223 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4224 audio_low_latency_hint_start();
4225 }
4226
Manish Dewangan21a850a2017-08-14 12:03:55 +05304227 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004228 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004229 if (ret < 0)
4230 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4231 }
4232
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004233 // consider a scenario where on pause lower layers are tear down.
4234 // so on resume, swap mixer control need to be sent only when
4235 // backend is active, hence rather than sending from enable device
4236 // sending it from start of streamtream
4237
4238 platform_set_swap_channels(adev, true);
4239
Haynes Mathew George380745d2017-10-04 15:27:45 -07004240 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304241 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004242 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004243error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004244 if (adev->haptic_pcm) {
4245 pcm_close(adev->haptic_pcm);
4246 adev->haptic_pcm = NULL;
4247 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004248 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304249 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004251error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304252 /*
4253 * sleep 50ms to allow sufficient time for kernel
4254 * drivers to recover incases like SSR.
4255 */
4256 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004257error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004258 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304259 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004260 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261}
4262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263static int check_input_parameters(uint32_t sample_rate,
4264 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004265 int channel_count,
4266 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004268 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304270 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4271 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4272 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004273 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004274 !audio_extn_compr_cap_format_supported(format) &&
4275 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004276 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004277
Aalique Grahame22e49102018-12-18 14:23:57 -08004278 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4279 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4280 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4281 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4282 return -EINVAL;
4283 }
4284
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004285 switch (channel_count) {
4286 case 1:
4287 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304288 case 3:
4289 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004290 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004291 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304292 case 10:
4293 case 12:
4294 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004295 break;
4296 default:
4297 ret = -EINVAL;
4298 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299
4300 switch (sample_rate) {
4301 case 8000:
4302 case 11025:
4303 case 12000:
4304 case 16000:
4305 case 22050:
4306 case 24000:
4307 case 32000:
4308 case 44100:
4309 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004310 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304311 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004312 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304313 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 break;
4315 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004316 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317 }
4318
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320}
4321
Naresh Tanniru04f71882018-06-26 17:46:22 +05304322
4323/** Add a value in a list if not already present.
4324 * @return true if value was successfully inserted or already present,
4325 * false if the list is full and does not contain the value.
4326 */
4327static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4328 for (size_t i = 0; i < list_length; i++) {
4329 if (list[i] == value) return true; // value is already present
4330 if (list[i] == 0) { // no values in this slot
4331 list[i] = value;
4332 return true; // value inserted
4333 }
4334 }
4335 return false; // could not insert value
4336}
4337
4338/** Add channel_mask in supported_channel_masks if not already present.
4339 * @return true if channel_mask was successfully inserted or already present,
4340 * false if supported_channel_masks is full and does not contain channel_mask.
4341 */
4342static void register_channel_mask(audio_channel_mask_t channel_mask,
4343 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4344 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4345 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4346}
4347
4348/** Add format in supported_formats if not already present.
4349 * @return true if format was successfully inserted or already present,
4350 * false if supported_formats is full and does not contain format.
4351 */
4352static void register_format(audio_format_t format,
4353 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4354 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4355 "%s: stream can not declare supporting its format %x", __func__, format);
4356}
4357/** Add sample_rate in supported_sample_rates if not already present.
4358 * @return true if sample_rate was successfully inserted or already present,
4359 * false if supported_sample_rates is full and does not contain sample_rate.
4360 */
4361static void register_sample_rate(uint32_t sample_rate,
4362 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4363 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4364 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4365}
4366
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004367static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4368{
4369 uint32_t high = num1, low = num2, temp = 0;
4370
4371 if (!num1 || !num2)
4372 return 0;
4373
4374 if (num1 < num2) {
4375 high = num2;
4376 low = num1;
4377 }
4378
4379 while (low != 0) {
4380 temp = low;
4381 low = high % low;
4382 high = temp;
4383 }
4384 return (num1 * num2)/high;
4385}
4386
4387static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4388{
4389 uint32_t remainder = 0;
4390
4391 if (!multiplier)
4392 return num;
4393
4394 remainder = num % multiplier;
4395 if (remainder)
4396 num += (multiplier - remainder);
4397
4398 return num;
4399}
4400
Aalique Grahame22e49102018-12-18 14:23:57 -08004401static size_t get_stream_buffer_size(size_t duration_ms,
4402 uint32_t sample_rate,
4403 audio_format_t format,
4404 int channel_count,
4405 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406{
4407 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004408 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409
Aalique Grahame22e49102018-12-18 14:23:57 -08004410 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004411 if (is_low_latency)
4412 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304413
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004414 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004415 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416
Ralf Herzbd08d632018-09-28 15:50:49 +02004417 /* make sure the size is multiple of 32 bytes and additionally multiple of
4418 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004419 * At 48 kHz mono 16-bit PCM:
4420 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4421 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004422 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004423 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004424 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004425
4426 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427}
4428
Aalique Grahame22e49102018-12-18 14:23:57 -08004429static size_t get_input_buffer_size(uint32_t sample_rate,
4430 audio_format_t format,
4431 int channel_count,
4432 bool is_low_latency)
4433{
4434 /* Don't know if USB HIFI in this context so use true to be conservative */
4435 if (check_input_parameters(sample_rate, format, channel_count,
4436 true /*is_usb_hifi */) != 0)
4437 return 0;
4438
4439 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4440 sample_rate,
4441 format,
4442 channel_count,
4443 is_low_latency);
4444}
4445
Derek Chenf6318be2017-06-12 17:16:24 -04004446size_t get_output_period_size(uint32_t sample_rate,
4447 audio_format_t format,
4448 int channel_count,
4449 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304450{
4451 size_t size = 0;
4452 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4453
4454 if ((duration == 0) || (sample_rate == 0) ||
4455 (bytes_per_sample == 0) || (channel_count == 0)) {
4456 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4457 bytes_per_sample, channel_count);
4458 return -EINVAL;
4459 }
4460
4461 size = (sample_rate *
4462 duration *
4463 bytes_per_sample *
4464 channel_count) / 1000;
4465 /*
4466 * To have same PCM samples for all channels, the buffer size requires to
4467 * be multiple of (number of channels * bytes per sample)
4468 * For writes to succeed, the buffer must be written at address which is multiple of 32
4469 */
4470 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4471
4472 return (size/(channel_count * bytes_per_sample));
4473}
4474
Zhou Song48453a02018-01-10 17:50:59 +08004475static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304476{
4477 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004478 uint64_t written_frames = 0;
4479 uint64_t kernel_frames = 0;
4480 uint64_t dsp_frames = 0;
4481 uint64_t signed_frames = 0;
4482 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304483
4484 /* This adjustment accounts for buffering after app processor.
4485 * It is based on estimated DSP latency per use case, rather than exact.
4486 */
George Gao9ba8a142020-07-23 14:30:03 -07004487 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004488 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304489
Zhou Song48453a02018-01-10 17:50:59 +08004490 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004491 written_frames = out->written /
4492 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4493
Ashish Jain5106d362016-05-11 19:23:33 +05304494 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4495 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4496 * hence only estimate.
4497 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004498 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4499 kernel_frames = kernel_buffer_size /
4500 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304501
Weiyin Jiang4813da12020-05-28 00:37:28 +08004502 if (written_frames >= (kernel_frames + dsp_frames))
4503 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304504
Zhou Song48453a02018-01-10 17:50:59 +08004505 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304506 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004507 if (timestamp != NULL )
4508 *timestamp = out->writeAt;
4509 } else if (timestamp != NULL) {
4510 clock_gettime(CLOCK_MONOTONIC, timestamp);
4511 }
4512 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304513
Weiyin Jiang4813da12020-05-28 00:37:28 +08004514 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4515 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304516
4517 return actual_frames_rendered;
4518}
4519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4521{
4522 struct stream_out *out = (struct stream_out *)stream;
4523
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525}
4526
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004527static int out_set_sample_rate(struct audio_stream *stream __unused,
4528 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529{
4530 return -ENOSYS;
4531}
4532
4533static size_t out_get_buffer_size(const struct audio_stream *stream)
4534{
4535 struct stream_out *out = (struct stream_out *)stream;
4536
Varun Balaraje49253e2017-07-06 19:48:56 +05304537 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304538 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304539 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304540 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4541 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4542 else
4543 return out->compr_config.fragment_size;
4544 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004545 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304546 else if (is_offload_usecase(out->usecase) &&
4547 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304548 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004549
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004550 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004551 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552}
4553
4554static uint32_t out_get_channels(const struct audio_stream *stream)
4555{
4556 struct stream_out *out = (struct stream_out *)stream;
4557
4558 return out->channel_mask;
4559}
4560
4561static audio_format_t out_get_format(const struct audio_stream *stream)
4562{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004563 struct stream_out *out = (struct stream_out *)stream;
4564
4565 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566}
4567
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004568static int out_set_format(struct audio_stream *stream __unused,
4569 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570{
4571 return -ENOSYS;
4572}
4573
4574static int out_standby(struct audio_stream *stream)
4575{
4576 struct stream_out *out = (struct stream_out *)stream;
4577 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004578 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004579
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304580 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4581 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004583 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004584 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004585 if (adev->adm_deregister_stream)
4586 adev->adm_deregister_stream(adev->adm_data, out->handle);
4587
Weiyin Jiang280ea742020-09-08 20:28:22 +08004588 if (is_offload_usecase(out->usecase)) {
4589 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004590 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004591 pthread_mutex_unlock(&out->latch_lock);
4592 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004593
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004594 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004596 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4597 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304598 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004599 pthread_mutex_unlock(&adev->lock);
4600 pthread_mutex_unlock(&out->lock);
4601 ALOGD("VOIP output entered standby");
4602 return 0;
4603 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004604 if (out->pcm) {
4605 pcm_close(out->pcm);
4606 out->pcm = NULL;
4607 }
Meng Wanga09da002020-04-20 12:56:04 +08004608 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4609 if (adev->haptic_pcm) {
4610 pcm_close(adev->haptic_pcm);
4611 adev->haptic_pcm = NULL;
4612 }
4613
4614 if (adev->haptic_buffer != NULL) {
4615 free(adev->haptic_buffer);
4616 adev->haptic_buffer = NULL;
4617 adev->haptic_buffer_size = 0;
4618 }
4619 adev->haptic_pcm_device_id = 0;
4620 }
4621
Haynes Mathew George16081042017-05-31 17:16:49 -07004622 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4623 do_stop = out->playback_started;
4624 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004625
4626 if (out->mmap_shared_memory_fd >= 0) {
4627 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4628 __func__, out->mmap_shared_memory_fd);
4629 close(out->mmap_shared_memory_fd);
4630 out->mmap_shared_memory_fd = -1;
4631 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004632 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004634 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304635 out->send_next_track_params = false;
4636 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004637 out->gapless_mdata.encoder_delay = 0;
4638 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004639 if (out->compr != NULL) {
4640 compress_close(out->compr);
4641 out->compr = NULL;
4642 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004643 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004644 if (do_stop) {
4645 stop_output_stream(out);
4646 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304647 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004648 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004649 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 }
4651 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004652 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653 return 0;
4654}
4655
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304656static int out_on_error(struct audio_stream *stream)
4657{
4658 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004659 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304660
4661 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004662 // always send CMD_ERROR for offload streams, this
4663 // is needed e.g. when SSR happens within compress_open
4664 // since the stream is active, offload_callback_thread is also active.
4665 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08004666 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004667 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004668 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004669 }
4670 pthread_mutex_unlock(&out->lock);
4671
4672 status = out_standby(&out->stream.common);
4673
4674 lock_output_stream(out);
4675 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004676 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304677 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304678
4679 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4680 ALOGD("Setting previous card status if offline");
4681 out->prev_card_status_offline = true;
4682 }
4683
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304684 pthread_mutex_unlock(&out->lock);
4685
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004686 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304687}
4688
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304689/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004690 * standby implementation without locks, assumes that the callee already
4691 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304692 */
4693int out_standby_l(struct audio_stream *stream)
4694{
4695 struct stream_out *out = (struct stream_out *)stream;
4696 struct audio_device *adev = out->dev;
4697
4698 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4699 stream, out->usecase, use_case_table[out->usecase]);
4700
4701 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004702 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304703 if (adev->adm_deregister_stream)
4704 adev->adm_deregister_stream(adev->adm_data, out->handle);
4705
Weiyin Jiang280ea742020-09-08 20:28:22 +08004706 if (is_offload_usecase(out->usecase)) {
4707 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304708 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004709 pthread_mutex_unlock(&out->latch_lock);
4710 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304711
4712 out->standby = true;
4713 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4714 voice_extn_compress_voip_close_output_stream(stream);
4715 out->started = 0;
4716 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004717 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304718 return 0;
4719 } else if (!is_offload_usecase(out->usecase)) {
4720 if (out->pcm) {
4721 pcm_close(out->pcm);
4722 out->pcm = NULL;
4723 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004724 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4725 if (adev->haptic_pcm) {
4726 pcm_close(adev->haptic_pcm);
4727 adev->haptic_pcm = NULL;
4728 }
4729
4730 if (adev->haptic_buffer != NULL) {
4731 free(adev->haptic_buffer);
4732 adev->haptic_buffer = NULL;
4733 adev->haptic_buffer_size = 0;
4734 }
4735 adev->haptic_pcm_device_id = 0;
4736 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304737 } else {
4738 ALOGD("copl(%p):standby", out);
4739 out->send_next_track_params = false;
4740 out->is_compr_metadata_avail = false;
4741 out->gapless_mdata.encoder_delay = 0;
4742 out->gapless_mdata.encoder_padding = 0;
4743 if (out->compr != NULL) {
4744 compress_close(out->compr);
4745 out->compr = NULL;
4746 }
4747 }
4748 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004749 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304750 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004751 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304752 return 0;
4753}
4754
Aalique Grahame22e49102018-12-18 14:23:57 -08004755static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756{
Aalique Grahame22e49102018-12-18 14:23:57 -08004757 struct stream_out *out = (struct stream_out *)stream;
4758
4759 // We try to get the lock for consistency,
4760 // but it isn't necessary for these variables.
4761 // If we're not in standby, we may be blocked on a write.
4762 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4763 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4764 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4765
Andy Hunga1f48fa2019-07-01 18:14:53 -07004766 char buffer[256]; // for statistics formatting
4767 if (!is_offload_usecase(out->usecase)) {
4768 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4769 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4770 }
4771
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004772 if (out->start_latency_ms.n > 0) {
4773 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4774 dprintf(fd, " Start latency ms: %s\n", buffer);
4775 }
4776
Aalique Grahame22e49102018-12-18 14:23:57 -08004777 if (locked) {
4778 pthread_mutex_unlock(&out->lock);
4779 }
4780
4781 // dump error info
4782 (void)error_log_dump(
4783 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785 return 0;
4786}
4787
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004788static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4789{
4790 int ret = 0;
4791 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004792
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004793 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004794 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004795 return -EINVAL;
4796 }
4797
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304798 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004799
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004800 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4801 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304802 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004803 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004804 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4805 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304806 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004807 }
4808
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004809 ALOGV("%s new encoder delay %u and padding %u", __func__,
4810 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4811
4812 return 0;
4813}
4814
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004815static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4816{
4817 return out == adev->primary_output || out == adev->voice_tx_output;
4818}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004819
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304820// note: this call is safe only if the stream_cb is
4821// removed first in close_output_stream (as is done now).
4822static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4823{
4824 if (!stream || !parms)
4825 return;
4826
4827 struct stream_out *out = (struct stream_out *)stream;
4828 struct audio_device *adev = out->dev;
4829
4830 card_status_t status;
4831 int card;
4832 if (parse_snd_card_status(parms, &card, &status) < 0)
4833 return;
4834
4835 pthread_mutex_lock(&adev->lock);
4836 bool valid_cb = (card == adev->snd_card);
4837 pthread_mutex_unlock(&adev->lock);
4838
4839 if (!valid_cb)
4840 return;
4841
4842 lock_output_stream(out);
4843 if (out->card_status != status)
4844 out->card_status = status;
4845 pthread_mutex_unlock(&out->lock);
4846
4847 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4848 use_case_table[out->usecase],
4849 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4850
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304851 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304852 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304853 if (voice_is_call_state_active(adev) &&
4854 out == adev->primary_output) {
4855 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4856 pthread_mutex_lock(&adev->lock);
4857 voice_stop_call(adev);
4858 adev->mode = AUDIO_MODE_NORMAL;
4859 pthread_mutex_unlock(&adev->lock);
4860 }
4861 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304862 return;
4863}
4864
Kevin Rocardfce19002017-08-07 19:21:36 -07004865static int get_alive_usb_card(struct str_parms* parms) {
4866 int card;
4867 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4868 !audio_extn_usb_alive(card)) {
4869 return card;
4870 }
4871 return -ENODEV;
4872}
4873
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004874int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004875 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004876{
4877 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004879 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880 bool bypass_a2dp = false;
4881 bool reconfig = false;
4882 unsigned long service_interval = 0;
4883
4884 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004885 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4886
4887 list_init(&new_devices);
4888 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004889
4890 lock_output_stream(out);
4891 pthread_mutex_lock(&adev->lock);
4892
4893 /*
4894 * When HDMI cable is unplugged the music playback is paused and
4895 * the policy manager sends routing=0. But the audioflinger continues
4896 * to write data until standby time (3sec). As the HDMI core is
4897 * turned off, the write gets blocked.
4898 * Avoid this by routing audio to speaker until standby.
4899 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004900 if (is_single_device_type_equal(&out->device_list,
4901 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004902 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004903 !audio_extn_passthru_is_passthrough_stream(out) &&
4904 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004906 }
4907 /*
4908 * When A2DP is disconnected the
4909 * music playback is paused and the policy manager sends routing=0
4910 * But the audioflinger continues to write data until standby time
4911 * (3sec). As BT is turned off, the write gets blocked.
4912 * Avoid this by routing audio to speaker until standby.
4913 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004914 if (is_a2dp_out_device_type(&out->device_list) &&
4915 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004916 !audio_extn_a2dp_source_is_ready() &&
4917 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004918 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004919 }
4920 /*
4921 * When USB headset is disconnected the music platback paused
4922 * and the policy manager send routing=0. But if the USB is connected
4923 * back before the standby time, AFE is not closed and opened
4924 * when USB is connected back. So routing to speker will guarantee
4925 * AFE reconfiguration and AFE will be opend once USB is connected again
4926 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004927 if (is_usb_out_device_type(&out->device_list) &&
4928 list_empty(&new_devices) &&
4929 !audio_extn_usb_connected(NULL)) {
4930 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4931 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004932 /* To avoid a2dp to sco overlapping / BT device improper state
4933 * check with BT lib about a2dp streaming support before routing
4934 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004935 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004936 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004937 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4938 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004939 //combo usecase just by pass a2dp
4940 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4941 bypass_a2dp = true;
4942 } else {
4943 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4944 /* update device to a2dp and don't route as BT returned error
4945 * However it is still possible a2dp routing called because
4946 * of current active device disconnection (like wired headset)
4947 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004948 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004949 pthread_mutex_unlock(&adev->lock);
4950 pthread_mutex_unlock(&out->lock);
4951 goto error;
4952 }
4953 }
4954 }
4955
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004956 // Workaround: If routing to an non existing usb device, fail gracefully
4957 // The routing request will otherwise block during 10 second
4958 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004959 if (is_usb_out_device_type(&new_devices)) {
4960 struct str_parms *parms =
4961 str_parms_create_str(get_usb_device_address(&new_devices));
4962 if (!parms)
4963 goto error;
4964 if ((card = get_alive_usb_card(parms)) >= 0) {
4965 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4966 pthread_mutex_unlock(&adev->lock);
4967 pthread_mutex_unlock(&out->lock);
4968 str_parms_destroy(parms);
4969 ret = -ENOSYS;
4970 goto error;
4971 }
4972 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004973 }
4974
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004975 // Workaround: If routing to an non existing hdmi device, fail gracefully
4976 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4977 (platform_get_edid_info_v2(adev->platform,
4978 out->extconn.cs.controller,
4979 out->extconn.cs.stream) != 0)) {
4980 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4981 pthread_mutex_unlock(&adev->lock);
4982 pthread_mutex_unlock(&out->lock);
4983 ret = -ENOSYS;
4984 goto error;
4985 }
4986
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004987 /*
4988 * select_devices() call below switches all the usecases on the same
4989 * backend to the new device. Refer to check_usecases_codec_backend() in
4990 * the select_devices(). But how do we undo this?
4991 *
4992 * For example, music playback is active on headset (deep-buffer usecase)
4993 * and if we go to ringtones and select a ringtone, low-latency usecase
4994 * will be started on headset+speaker. As we can't enable headset+speaker
4995 * and headset devices at the same time, select_devices() switches the music
4996 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4997 * So when the ringtone playback is completed, how do we undo the same?
4998 *
4999 * We are relying on the out_set_parameters() call on deep-buffer output,
5000 * once the ringtone playback is ended.
5001 * NOTE: We should not check if the current devices are same as new devices.
5002 * Because select_devices() must be called to switch back the music
5003 * playback to headset.
5004 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005005 if (!list_empty(&new_devices)) {
5006 bool same_dev = compare_devices(&out->device_list, &new_devices);
5007 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005008
5009 if (output_drives_call(adev, out)) {
5010 if (!voice_is_call_state_active(adev)) {
5011 if (adev->mode == AUDIO_MODE_IN_CALL) {
5012 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005013 ret = voice_start_call(adev);
5014 }
5015 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005016 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 adev->current_call_output = out;
5018 voice_update_devices_for_all_voice_usecases(adev);
5019 }
5020 }
5021
Mingshu Pang971ff702020-09-09 15:28:22 +08005022 if (is_usb_out_device_type(&out->device_list)) {
5023 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5024 audio_extn_usb_set_service_interval(true /*playback*/,
5025 service_interval,
5026 &reconfig);
5027 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5028 }
5029
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005030 if (!out->standby) {
5031 if (!same_dev) {
5032 ALOGV("update routing change");
5033 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5034 adev->perf_lock_opts,
5035 adev->perf_lock_opts_size);
5036 if (adev->adm_on_routing_change)
5037 adev->adm_on_routing_change(adev->adm_data,
5038 out->handle);
5039 }
5040 if (!bypass_a2dp) {
5041 select_devices(adev, out->usecase);
5042 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005043 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5044 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005045 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005046 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005047 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005048 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 }
5050
5051 if (!same_dev) {
5052 // on device switch force swap, lower functions will make sure
5053 // to check if swap is allowed or not.
5054 platform_set_swap_channels(adev, true);
5055 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5056 }
Zhou Songd01e7a22020-09-23 22:49:01 +08005057 if (is_offload_usecase(out->usecase) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005058 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005059 pthread_mutex_lock(&out->latch_lock);
5060 if (out->a2dp_compress_mute) {
5061 out->a2dp_compress_mute = false;
5062 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5063 }
5064 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005065 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5066 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5067 }
5068 }
5069 }
5070
5071 pthread_mutex_unlock(&adev->lock);
5072 pthread_mutex_unlock(&out->lock);
5073
5074 /*handles device and call state changes*/
5075 audio_extn_extspk_update(adev->extspk);
5076
5077error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005078 ALOGV("%s: exit: code(%d)", __func__, ret);
5079 return ret;
5080}
5081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5083{
5084 struct stream_out *out = (struct stream_out *)stream;
5085 struct audio_device *adev = out->dev;
5086 struct str_parms *parms;
5087 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005088 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005089 int ext_controller = -1;
5090 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091
sangwoobc677242013-08-08 16:53:43 +09005092 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005093 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305095 if (!parms)
5096 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005097
5098 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5099 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005100 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005101 out->extconn.cs.controller = ext_controller;
5102 out->extconn.cs.stream = ext_stream;
5103 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5104 use_case_table[out->usecase], out->extconn.cs.controller,
5105 out->extconn.cs.stream);
5106 }
5107
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005108 if (out == adev->primary_output) {
5109 pthread_mutex_lock(&adev->lock);
5110 audio_extn_set_parameters(adev, parms);
5111 pthread_mutex_unlock(&adev->lock);
5112 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005113 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005114 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005115 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005116
5117 audio_extn_dts_create_state_notifier_node(out->usecase);
5118 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5119 popcount(out->channel_mask),
5120 out->playback_started);
5121
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005122 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005123 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005124
Surendar Karkaf51b5842018-04-26 11:28:38 +05305125 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5126 sizeof(value));
5127 if (err >= 0) {
5128 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5129 audio_extn_send_dual_mono_mixing_coefficients(out);
5130 }
5131
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305132 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5133 if (err >= 0) {
5134 strlcpy(out->profile, value, sizeof(out->profile));
5135 ALOGV("updating stream profile with value '%s'", out->profile);
5136 lock_output_stream(out);
5137 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5138 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005139 &out->device_list, out->flags,
5140 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305141 out->sample_rate, out->bit_width,
5142 out->channel_mask, out->profile,
5143 &out->app_type_cfg);
5144 pthread_mutex_unlock(&out->lock);
5145 }
5146
Alexy Joseph98988832017-01-13 14:56:59 -08005147 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005148 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5149 // and vendor.audio.hal.output.suspend.supported is set to true
5150 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005151 //check suspend parameter only for low latency and if the property
5152 //is enabled
5153 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5154 ALOGI("%s: got suspend_playback %s", __func__, value);
5155 lock_output_stream(out);
5156 if (!strncmp(value, "false", 5)) {
5157 //suspend_playback=false is supposed to set QOS value back to 75%
5158 //the mixer control sent with value Enable will achieve that
5159 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5160 } else if (!strncmp (value, "true", 4)) {
5161 //suspend_playback=true is supposed to remove QOS value
5162 //resetting the mixer control will set the default value
5163 //for the mixer control which is Disable and this removes the QOS vote
5164 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5165 } else {
5166 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5167 " got %s", __func__, value);
5168 ret = -1;
5169 }
5170
5171 if (ret != 0) {
5172 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5173 __func__, out->pm_qos_mixer_path, ret);
5174 }
5175
5176 pthread_mutex_unlock(&out->lock);
5177 }
5178 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005179
Alexy Joseph98988832017-01-13 14:56:59 -08005180 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005181 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305182error:
Eric Laurent994a6932013-07-17 11:51:42 -07005183 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005184 return ret;
5185}
5186
Paul McLeana50b7332018-12-17 08:24:21 -07005187static int in_set_microphone_direction(const struct audio_stream_in *stream,
5188 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005189 struct stream_in *in = (struct stream_in *)stream;
5190
5191 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5192
5193 in->direction = dir;
5194
5195 if (in->standby)
5196 return 0;
5197
5198 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005199}
5200
5201static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005202 struct stream_in *in = (struct stream_in *)stream;
5203
5204 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5205
5206 if (zoom > 1.0 || zoom < -1.0)
5207 return -EINVAL;
5208
5209 in->zoom = zoom;
5210
5211 if (in->standby)
5212 return 0;
5213
5214 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005215}
5216
5217
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005218static bool stream_get_parameter_channels(struct str_parms *query,
5219 struct str_parms *reply,
5220 audio_channel_mask_t *supported_channel_masks) {
5221 int ret = -1;
5222 char value[512];
5223 bool first = true;
5224 size_t i, j;
5225
5226 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5227 ret = 0;
5228 value[0] = '\0';
5229 i = 0;
5230 while (supported_channel_masks[i] != 0) {
5231 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5232 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5233 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305234 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005235
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305236 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005237 first = false;
5238 break;
5239 }
5240 }
5241 i++;
5242 }
5243 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5244 }
5245 return ret == 0;
5246}
5247
5248static bool stream_get_parameter_formats(struct str_parms *query,
5249 struct str_parms *reply,
5250 audio_format_t *supported_formats) {
5251 int ret = -1;
5252 char value[256];
5253 size_t i, j;
5254 bool first = true;
5255
5256 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5257 ret = 0;
5258 value[0] = '\0';
5259 i = 0;
5260 while (supported_formats[i] != 0) {
5261 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5262 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5263 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305264 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005265 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305266 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005267 first = false;
5268 break;
5269 }
5270 }
5271 i++;
5272 }
5273 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5274 }
5275 return ret == 0;
5276}
5277
5278static bool stream_get_parameter_rates(struct str_parms *query,
5279 struct str_parms *reply,
5280 uint32_t *supported_sample_rates) {
5281
5282 int i;
5283 char value[256];
5284 int ret = -1;
5285 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5286 ret = 0;
5287 value[0] = '\0';
5288 i=0;
5289 int cursor = 0;
5290 while (supported_sample_rates[i]) {
5291 int avail = sizeof(value) - cursor;
5292 ret = snprintf(value + cursor, avail, "%s%d",
5293 cursor > 0 ? "|" : "",
5294 supported_sample_rates[i]);
5295 if (ret < 0 || ret >= avail) {
5296 // if cursor is at the last element of the array
5297 // overwrite with \0 is duplicate work as
5298 // snprintf already put a \0 in place.
5299 // else
5300 // we had space to write the '|' at value[cursor]
5301 // (which will be overwritten) or no space to fill
5302 // the first element (=> cursor == 0)
5303 value[cursor] = '\0';
5304 break;
5305 }
5306 cursor += ret;
5307 ++i;
5308 }
5309 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5310 value);
5311 }
5312 return ret >= 0;
5313}
5314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5316{
5317 struct stream_out *out = (struct stream_out *)stream;
5318 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005319 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 char value[256];
5321 struct str_parms *reply = str_parms_create();
5322 size_t i, j;
5323 int ret;
5324 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005325
5326 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005327 if (reply) {
5328 str_parms_destroy(reply);
5329 }
5330 if (query) {
5331 str_parms_destroy(query);
5332 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005333 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5334 return NULL;
5335 }
5336
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005337 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5339 if (ret >= 0) {
5340 value[0] = '\0';
5341 i = 0;
5342 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005343 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5344 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005345 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005346 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005348 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 first = false;
5350 break;
5351 }
5352 }
5353 i++;
5354 }
5355 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5356 str = str_parms_to_str(reply);
5357 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005358 voice_extn_out_get_parameters(out, query, reply);
5359 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005360 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005361
Alexy Joseph62142aa2015-11-16 15:10:34 -08005362
5363 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5364 if (ret >= 0) {
5365 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305366 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5367 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005368 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305369 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005370 } else {
5371 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305372 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005373 }
5374 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005375 if (str)
5376 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005377 str = str_parms_to_str(reply);
5378 }
5379
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005380 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5381 if (ret >= 0) {
5382 value[0] = '\0';
5383 i = 0;
5384 first = true;
5385 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005386 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5387 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005388 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005389 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005390 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005391 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005392 first = false;
5393 break;
5394 }
5395 }
5396 i++;
5397 }
5398 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005399 if (str)
5400 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005401 str = str_parms_to_str(reply);
5402 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005403
5404 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5405 if (ret >= 0) {
5406 value[0] = '\0';
5407 i = 0;
5408 first = true;
5409 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005410 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5411 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005412 if (!first) {
5413 strlcat(value, "|", sizeof(value));
5414 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005415 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005416 first = false;
5417 break;
5418 }
5419 }
5420 i++;
5421 }
5422 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5423 if (str)
5424 free(str);
5425 str = str_parms_to_str(reply);
5426 }
5427
Alexy Joseph98988832017-01-13 14:56:59 -08005428 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5429 //only low latency track supports suspend_resume
5430 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005431 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005432 if (str)
5433 free(str);
5434 str = str_parms_to_str(reply);
5435 }
5436
5437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005438 str_parms_destroy(query);
5439 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005440 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441 return str;
5442}
5443
5444static uint32_t out_get_latency(const struct audio_stream_out *stream)
5445{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005446 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005447 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005448 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449
Alexy Josephaa54c872014-12-03 02:46:47 -08005450 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305451 lock_output_stream(out);
5452 latency = audio_extn_utils_compress_get_dsp_latency(out);
5453 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005454 } else if ((out->realtime) ||
5455 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005456 // since the buffer won't be filled up faster than realtime,
5457 // return a smaller number
5458 if (out->config.rate)
5459 period_ms = (out->af_period_multiplier * out->config.period_size *
5460 1000) / (out->config.rate);
5461 else
5462 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005463 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005464 } else {
5465 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005466 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005467 }
5468
Zhou Songd2537a02020-06-11 22:04:46 +08005469 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005470 latency += audio_extn_a2dp_get_encoder_latency();
5471
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305472 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005473 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005474}
5475
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305476static float AmpToDb(float amplification)
5477{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305478 float db = DSD_VOLUME_MIN_DB;
5479 if (amplification > 0) {
5480 db = 20 * log10(amplification);
5481 if(db < DSD_VOLUME_MIN_DB)
5482 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305483 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305484 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305485}
5486
Arun Mirpuri5d170872019-03-26 13:21:31 -07005487static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5488 float right)
5489{
5490 struct stream_out *out = (struct stream_out *)stream;
5491 long volume = 0;
5492 char mixer_ctl_name[128] = "";
5493 struct audio_device *adev = out->dev;
5494 struct mixer_ctl *ctl = NULL;
5495 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5496 PCM_PLAYBACK);
5497
5498 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5499 "Playback %d Volume", pcm_device_id);
5500 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5501 if (!ctl) {
5502 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5503 __func__, mixer_ctl_name);
5504 return -EINVAL;
5505 }
5506 if (left != right)
5507 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5508 __func__, left, right);
5509 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5510 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5511 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5512 __func__, mixer_ctl_name, volume);
5513 return -EINVAL;
5514 }
5515 return 0;
5516}
5517
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305518static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5519 float right)
5520{
5521 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305522 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305523 char mixer_ctl_name[128];
5524 struct audio_device *adev = out->dev;
5525 struct mixer_ctl *ctl;
5526 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5527 PCM_PLAYBACK);
5528
5529 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5530 "Compress Playback %d Volume", pcm_device_id);
5531 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5532 if (!ctl) {
5533 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5534 __func__, mixer_ctl_name);
5535 return -EINVAL;
5536 }
5537 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5538 __func__, mixer_ctl_name, left, right);
5539 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5540 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5541 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5542
5543 return 0;
5544}
5545
Zhou Song2b8f28f2017-09-11 10:51:38 +08005546static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5547 float right)
5548{
5549 struct stream_out *out = (struct stream_out *)stream;
5550 char mixer_ctl_name[] = "App Type Gain";
5551 struct audio_device *adev = out->dev;
5552 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305553 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005554
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005555 if (!is_valid_volume(left, right)) {
5556 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5557 __func__, left, right);
5558 return -EINVAL;
5559 }
5560
Zhou Song2b8f28f2017-09-11 10:51:38 +08005561 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5562 if (!ctl) {
5563 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5564 __func__, mixer_ctl_name);
5565 return -EINVAL;
5566 }
5567
5568 set_values[0] = 0; //0: Rx Session 1:Tx Session
5569 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305570 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5571 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005572
5573 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5574 return 0;
5575}
5576
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305577static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5578 float right)
5579{
5580 struct stream_out *out = (struct stream_out *)stream;
5581 /* Volume control for pcm playback */
5582 if (left != right) {
5583 return -EINVAL;
5584 } else {
5585 char mixer_ctl_name[128];
5586 struct audio_device *adev = out->dev;
5587 struct mixer_ctl *ctl;
5588 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5589 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5590 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5591 if (!ctl) {
5592 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5593 return -EINVAL;
5594 }
5595
5596 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5597 int ret = mixer_ctl_set_value(ctl, 0, volume);
5598 if (ret < 0) {
5599 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5600 return -EINVAL;
5601 }
5602
5603 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5604
5605 return 0;
5606 }
5607}
5608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609static int out_set_volume(struct audio_stream_out *stream, float left,
5610 float right)
5611{
Eric Laurenta9024de2013-04-04 09:19:12 -07005612 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005613 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305614 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005615
Arun Mirpuri5d170872019-03-26 13:21:31 -07005616 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005617 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5618 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiang280ea742020-09-08 20:28:22 +08005619 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005620 out->muted = (left == 0.0f);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005621 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005622 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005623 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305624 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005625 /*
5626 * Set mute or umute on HDMI passthrough stream.
5627 * Only take left channel into account.
5628 * Mute is 0 and unmute 1
5629 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305630 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305631 } else if (out->format == AUDIO_FORMAT_DSD){
5632 char mixer_ctl_name[128] = "DSD Volume";
5633 struct audio_device *adev = out->dev;
5634 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5635
5636 if (!ctl) {
5637 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5638 __func__, mixer_ctl_name);
5639 return -EINVAL;
5640 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305641 volume[0] = (long)(AmpToDb(left));
5642 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305643 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5644 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005645 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005646 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005647 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5648 struct listnode *node = NULL;
5649 list_for_each(node, &adev->active_outputs_list) {
5650 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5651 streams_output_ctxt_t,
5652 list);
5653 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5654 out->volume_l = out_ctxt->output->volume_l;
5655 out->volume_r = out_ctxt->output->volume_r;
5656 }
5657 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005658 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005659 if (!out->a2dp_compress_mute) {
5660 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5661 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005662 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005663 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005664 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005665 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005666 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305667 if (!out->a2dp_compress_mute)
5668 ret = out_set_compr_volume(stream, left, right);
5669 out->volume_l = left;
5670 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005671 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305672 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005673 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005674 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005675 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5676 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5677 if (!out->standby) {
5678 audio_extn_utils_send_app_type_gain(out->dev,
5679 out->app_type_cfg.app_type,
5680 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005681 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005682 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005683 out->volume_l = left;
5684 out->volume_r = right;
5685 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005686 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5687 ALOGV("%s: MMAP set volume called", __func__);
5688 if (!out->standby)
5689 ret = out_set_mmap_volume(stream, left, right);
5690 out->volume_l = left;
5691 out->volume_r = right;
5692 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305693 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305694 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5695 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305696 /* Volume control for pcm playback */
5697 if (!out->standby)
5698 ret = out_set_pcm_volume(stream, left, right);
5699 else
5700 out->apply_volume = true;
5701
5702 out->volume_l = left;
5703 out->volume_r = right;
5704 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005705 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5706 ALOGV("%s: bus device set volume called", __func__);
5707 if (!out->standby)
5708 ret = out_set_pcm_volume(stream, left, right);
5709 out->volume_l = left;
5710 out->volume_r = right;
5711 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005712 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005714 return -ENOSYS;
5715}
5716
Zhou Songc9672822017-08-16 16:01:39 +08005717static void update_frames_written(struct stream_out *out, size_t bytes)
5718{
5719 size_t bpf = 0;
5720
5721 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5722 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5723 bpf = 1;
5724 else if (!is_offload_usecase(out->usecase))
5725 bpf = audio_bytes_per_sample(out->format) *
5726 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005727
5728 pthread_mutex_lock(&out->position_query_lock);
5729 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005730 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005731 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5732 }
5733 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005734}
5735
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005736int split_and_write_audio_haptic_data(struct stream_out *out,
5737 const void *buffer, size_t bytes_to_write)
5738{
5739 struct audio_device *adev = out->dev;
5740
5741 int ret = 0;
5742 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5743 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5744 size_t frame_size = channel_count * bytes_per_sample;
5745 size_t frame_count = bytes_to_write / frame_size;
5746
5747 bool force_haptic_path =
5748 property_get_bool("vendor.audio.test_haptic", false);
5749
5750 // extract Haptics data from Audio buffer
5751 bool alloc_haptic_buffer = false;
5752 int haptic_channel_count = adev->haptics_config.channels;
5753 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5754 size_t audio_frame_size = frame_size - haptic_frame_size;
5755 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5756
5757 if (adev->haptic_buffer == NULL) {
5758 alloc_haptic_buffer = true;
5759 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5760 free(adev->haptic_buffer);
5761 adev->haptic_buffer_size = 0;
5762 alloc_haptic_buffer = true;
5763 }
5764
5765 if (alloc_haptic_buffer) {
5766 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005767 if(adev->haptic_buffer == NULL) {
5768 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5769 return -ENOMEM;
5770 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005771 adev->haptic_buffer_size = total_haptic_buffer_size;
5772 }
5773
5774 size_t src_index = 0, aud_index = 0, hap_index = 0;
5775 uint8_t *audio_buffer = (uint8_t *)buffer;
5776 uint8_t *haptic_buffer = adev->haptic_buffer;
5777
5778 // This is required for testing only. This works for stereo data only.
5779 // One channel is fed to audio stream and other to haptic stream for testing.
5780 if (force_haptic_path)
5781 audio_frame_size = haptic_frame_size = bytes_per_sample;
5782
5783 for (size_t i = 0; i < frame_count; i++) {
5784 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5785 audio_frame_size);
5786 aud_index += audio_frame_size;
5787 src_index += audio_frame_size;
5788
5789 if (adev->haptic_pcm)
5790 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5791 haptic_frame_size);
5792 hap_index += haptic_frame_size;
5793 src_index += haptic_frame_size;
5794
5795 // This is required for testing only.
5796 // Discard haptic channel data.
5797 if (force_haptic_path)
5798 src_index += haptic_frame_size;
5799 }
5800
5801 // write to audio pipeline
5802 ret = pcm_write(out->pcm, (void *)audio_buffer,
5803 frame_count * audio_frame_size);
5804
5805 // write to haptics pipeline
5806 if (adev->haptic_pcm)
5807 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5808 frame_count * haptic_frame_size);
5809
5810 return ret;
5811}
5812
Aalique Grahame22e49102018-12-18 14:23:57 -08005813#ifdef NO_AUDIO_OUT
5814static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5815 const void *buffer __unused, size_t bytes)
5816{
5817 struct stream_out *out = (struct stream_out *)stream;
5818
5819 /* No Output device supported other than BT for playback.
5820 * Sleep for the amount of buffer duration
5821 */
5822 lock_output_stream(out);
5823 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5824 (const struct audio_stream_out *)&out->stream) /
5825 out_get_sample_rate(&out->stream.common));
5826 pthread_mutex_unlock(&out->lock);
5827 return bytes;
5828}
5829#endif
5830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005831static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5832 size_t bytes)
5833{
5834 struct stream_out *out = (struct stream_out *)stream;
5835 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005836 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305837 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005838 const size_t frame_size = audio_stream_out_frame_size(stream);
5839 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305840 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005841 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005842
Haynes Mathew George380745d2017-10-04 15:27:45 -07005843 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005844 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305845
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305846 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005847
Dhananjay Kumarac341582017-02-23 23:42:25 +05305848 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305849 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305850 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5851 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005852 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305853 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305854 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305855 ALOGD(" %s: sound card is not active/SSR state", __func__);
5856 ret= -EIO;
5857 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305858 }
5859 }
5860
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305861 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305862 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305863 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305864 goto exit;
5865 }
5866
Haynes Mathew George16081042017-05-31 17:16:49 -07005867 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5868 ret = -EINVAL;
5869 goto exit;
5870 }
5871
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005872 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305873 !out->is_iec61937_info_available) {
5874
5875 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5876 out->is_iec61937_info_available = true;
5877 } else if (audio_extn_passthru_is_enabled()) {
5878 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305879 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305880
5881 if((out->format == AUDIO_FORMAT_DTS) ||
5882 (out->format == AUDIO_FORMAT_DTS_HD)) {
5883 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5884 buffer, bytes);
5885 if (ret) {
5886 if (ret != -ENOSYS) {
5887 out->is_iec61937_info_available = false;
5888 ALOGD("iec61937 transmission info not yet updated retry");
5889 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305890 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305891 /* if stream has started and after that there is
5892 * stream config change (iec transmission config)
5893 * then trigger select_device to update backend configuration.
5894 */
5895 out->stream_config_changed = true;
5896 pthread_mutex_lock(&adev->lock);
5897 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305898 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005899 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305900 ret = -EINVAL;
5901 goto exit;
5902 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305903 pthread_mutex_unlock(&adev->lock);
5904 out->stream_config_changed = false;
5905 out->is_iec61937_info_available = true;
5906 }
5907 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305908
Meng Wang4c32fb42020-01-16 17:57:11 +08005909#ifdef AUDIO_GKI_ENABLED
5910 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5911 compr_passthr = out->compr_config.codec->reserved[0];
5912#else
5913 compr_passthr = out->compr_config.codec->compr_passthr;
5914#endif
5915
Garmond Leung317cbf12017-09-13 16:20:50 -07005916 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005917 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305918 (out->is_iec61937_info_available == true)) {
5919 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5920 ret = -EINVAL;
5921 goto exit;
5922 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305923 }
5924 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305925
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005926 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005927 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005928 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5929 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005930 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305931 ret = -EIO;
5932 goto exit;
5933 }
5934 }
5935 }
5936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005937 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005938 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005939 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5940
Eric Laurent150dbfe2013-02-27 14:31:02 -08005941 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005942 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5943 ret = voice_extn_compress_voip_start_output_stream(out);
5944 else
5945 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005946 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005947 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005948 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005949 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005950 goto exit;
5951 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305952 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005953 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005954
5955 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005956 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005957 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305958 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005959 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005960 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305961
5962 if ((out->is_iec61937_info_available == true) &&
5963 (audio_extn_passthru_is_passthrough_stream(out))&&
5964 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5965 ret = -EINVAL;
5966 goto exit;
5967 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305968 if (out->set_dual_mono)
5969 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005970
5971 // log startup time in ms.
5972 simple_stats_log(
5973 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005976 if (adev->is_channel_status_set == false &&
5977 compare_device_type(&out->device_list,
5978 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005979 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305980 adev->is_channel_status_set = true;
5981 }
5982
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305983 if ((adev->use_old_pspd_mix_ctrl == true) &&
5984 (out->pspd_coeff_sent == false)) {
5985 /*
5986 * Need to resend pspd coefficients after stream started for
5987 * older kernel version as it does not save the coefficients
5988 * and also stream has to be started for coeff to apply.
5989 */
5990 usecase = get_usecase_from_list(adev, out->usecase);
5991 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305992 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305993 out->pspd_coeff_sent = true;
5994 }
5995 }
5996
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005997 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005998 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005999 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006000 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006001 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6002 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306003 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6004 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006005 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306006 out->send_next_track_params = false;
6007 out->is_compr_metadata_avail = false;
6008 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006009 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306010 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306011 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006012
Ashish Jain83a6cc22016-06-28 14:34:17 +05306013 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306014 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306015 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306016 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006017 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306018 return -EINVAL;
6019 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306020 audio_format_t dst_format = out->hal_op_format;
6021 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306022
Dieter Luecking5d57def2018-09-07 14:23:37 +02006023 /* prevent division-by-zero */
6024 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6025 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6026 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6027 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306028 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006029 ATRACE_END();
6030 return -EINVAL;
6031 }
6032
Ashish Jainf1eaa582016-05-23 20:54:24 +05306033 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6034 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6035
Ashish Jain83a6cc22016-06-28 14:34:17 +05306036 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306037 dst_format,
6038 buffer,
6039 src_format,
6040 frames);
6041
Ashish Jain83a6cc22016-06-28 14:34:17 +05306042 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306043 bytes_to_write);
6044
6045 /*Convert written bytes in audio flinger format*/
6046 if (ret > 0)
6047 ret = ((ret * format_to_bitwidth_table[out->format]) /
6048 format_to_bitwidth_table[dst_format]);
6049 }
6050 } else
6051 ret = compress_write(out->compr, buffer, bytes);
6052
Zhou Songc9672822017-08-16 16:01:39 +08006053 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6054 update_frames_written(out, bytes);
6055
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306056 if (ret < 0)
6057 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006058 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306059 /*msg to cb thread only if non blocking write is enabled*/
6060 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306061 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006062 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306063 } else if (-ENETRESET == ret) {
6064 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306065 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306066 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306067 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006068 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306069 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006070 }
Ashish Jain5106d362016-05-11 19:23:33 +05306071
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306072 /* Call compr start only when non-zero bytes of data is there to be rendered */
6073 if (!out->playback_started && ret > 0) {
6074 int status = compress_start(out->compr);
6075 if (status < 0) {
6076 ret = status;
6077 ALOGE("%s: compr start failed with err %d", __func__, errno);
6078 goto exit;
6079 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006080 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006081 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006082 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006083 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006084 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006085
6086 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6087 popcount(out->channel_mask),
6088 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006089 }
6090 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006091 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006092 return ret;
6093 } else {
6094 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006095 size_t bytes_to_write = bytes;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006096 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006097 if (out->muted)
6098 memset((void *)buffer, 0, bytes);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006099 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006100 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6101 __func__, frames, frame_size, bytes_to_write);
6102
Aalique Grahame22e49102018-12-18 14:23:57 -08006103 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006104 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6105 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6106 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006107 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6108 int16_t *src = (int16_t *)buffer;
6109 int16_t *dst = (int16_t *)buffer;
6110
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006111 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006112 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006113 "out_write called for %s use case with wrong properties",
6114 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006115
6116 /*
6117 * FIXME: this can be removed once audio flinger mixer supports
6118 * mono output
6119 */
6120
6121 /*
6122 * Code below goes over each frame in the buffer and adds both
6123 * L and R samples and then divides by 2 to convert to mono
6124 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006125 if (channel_count == 2) {
6126 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6127 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6128 }
6129 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006130 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006131 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006132
6133 // Note: since out_get_presentation_position() is called alternating with out_write()
6134 // by AudioFlinger, we can check underruns using the prior timestamp read.
6135 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6136 if (out->last_fifo_valid) {
6137 // compute drain to see if there is an underrun.
6138 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306139 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6140 int64_t frames_by_time =
6141 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6142 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006143 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6144
6145 if (underrun > 0) {
6146 simple_stats_log(&out->fifo_underruns, underrun);
6147
6148 ALOGW("%s: underrun(%lld) "
6149 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6150 __func__,
6151 (long long)out->fifo_underruns.n,
6152 (long long)frames_by_time,
6153 (long long)out->last_fifo_frames_remaining);
6154 }
6155 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6156 }
6157
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306158 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006160 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006161
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006162 if (out->config.rate)
6163 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6164 out->config.rate;
6165
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006166 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006167 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6168
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006169 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006170 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006171 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306172 out->convert_buffer != NULL) {
6173
6174 memcpy_by_audio_format(out->convert_buffer,
6175 out->hal_op_format,
6176 buffer,
6177 out->hal_ip_format,
6178 out->config.period_size * out->config.channels);
6179
6180 ret = pcm_write(out->pcm, out->convert_buffer,
6181 (out->config.period_size *
6182 out->config.channels *
6183 format_to_bitwidth_table[out->hal_op_format]));
6184 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306185 /*
6186 * To avoid underrun in DSP when the application is not pumping
6187 * data at required rate, check for the no. of bytes and ignore
6188 * pcm_write if it is less than actual buffer size.
6189 * It is a work around to a change in compress VOIP driver.
6190 */
6191 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6192 bytes < (out->config.period_size * out->config.channels *
6193 audio_bytes_per_sample(out->format))) {
6194 size_t voip_buf_size =
6195 out->config.period_size * out->config.channels *
6196 audio_bytes_per_sample(out->format);
6197 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6198 __func__, bytes, voip_buf_size);
6199 usleep(((uint64_t)voip_buf_size - bytes) *
6200 1000000 / audio_stream_out_frame_size(stream) /
6201 out_get_sample_rate(&out->stream.common));
6202 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006203 } else {
6204 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6205 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6206 else
6207 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6208 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306209 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006210
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006211 release_out_focus(out);
6212
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306213 if (ret < 0)
6214 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006215 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306216 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006218 }
6219
6220exit:
Zhou Songc9672822017-08-16 16:01:39 +08006221 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306222 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306223 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306224 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006225 pthread_mutex_unlock(&out->lock);
6226
6227 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006228 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006229 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306230 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306231 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306232 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306233 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306234 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306235 out->standby = true;
6236 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306237 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006238 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6239 /* prevent division-by-zero */
6240 uint32_t stream_size = audio_stream_out_frame_size(stream);
6241 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006242
Dieter Luecking5d57def2018-09-07 14:23:37 +02006243 if ((stream_size == 0) || (srate == 0)) {
6244 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6245 ATRACE_END();
6246 return -EINVAL;
6247 }
6248 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6249 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006250 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306251 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006252 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006253 return ret;
6254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006256 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257 return bytes;
6258}
6259
6260static int out_get_render_position(const struct audio_stream_out *stream,
6261 uint32_t *dsp_frames)
6262{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006263 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006264
6265 if (dsp_frames == NULL)
6266 return -EINVAL;
6267
6268 *dsp_frames = 0;
6269 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006270 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306271
6272 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6273 * this operation and adev_close_output_stream(where out gets reset).
6274 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306275 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006276 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306277 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006278 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306279 return 0;
6280 }
6281
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006282 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306283 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306284 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006285 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306286 if (ret < 0)
6287 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006288 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306289 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006290 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306291 if (-ENETRESET == ret) {
6292 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306293 out->card_status = CARD_STATUS_OFFLINE;
6294 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306295 } else if(ret < 0) {
6296 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306297 ret = -EINVAL;
6298 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306299 /*
6300 * Handle corner case where compress session is closed during SSR
6301 * and timestamp is queried
6302 */
6303 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306304 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306305 } else if (out->prev_card_status_offline) {
6306 ALOGE("ERROR: previously sound card was offline,return error");
6307 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306308 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306309 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006310 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306311 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306312 pthread_mutex_unlock(&out->lock);
6313 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006314 } else if (audio_is_linear_pcm(out->format)) {
6315 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006316 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006317 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006318 } else
6319 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006320}
6321
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006322static int out_add_audio_effect(const struct audio_stream *stream __unused,
6323 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006324{
6325 return 0;
6326}
6327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006328static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6329 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006330{
6331 return 0;
6332}
6333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006334static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6335 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006336{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306337 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006338}
6339
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006340static int out_get_presentation_position(const struct audio_stream_out *stream,
6341 uint64_t *frames, struct timespec *timestamp)
6342{
6343 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306344 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006345 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006346
Ashish Jain5106d362016-05-11 19:23:33 +05306347 /* below piece of code is not guarded against any lock because audioFliner serializes
6348 * this operation and adev_close_output_stream( where out gets reset).
6349 */
6350 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306351 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006352 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306353 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6354 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6355 return 0;
6356 }
6357
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006358 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006359
Ashish Jain5106d362016-05-11 19:23:33 +05306360 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6361 ret = compress_get_tstamp(out->compr, &dsp_frames,
6362 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006363 // Adjustment accounts for A2dp encoder latency with offload usecases
6364 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006365 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006366 unsigned long offset =
6367 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6368 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6369 }
Ashish Jain5106d362016-05-11 19:23:33 +05306370 ALOGVV("%s rendered frames %ld sample_rate %d",
6371 __func__, dsp_frames, out->sample_rate);
6372 *frames = dsp_frames;
6373 if (ret < 0)
6374 ret = -errno;
6375 if (-ENETRESET == ret) {
6376 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306377 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306378 ret = -EINVAL;
6379 } else
6380 ret = 0;
6381 /* this is the best we can do */
6382 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006383 } else {
6384 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006385 unsigned int avail;
6386 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006387 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006388 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006389
Andy Hunga1f48fa2019-07-01 18:14:53 -07006390 if (out->kernel_buffer_size > avail) {
6391 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6392 } else {
6393 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6394 __func__, avail, out->kernel_buffer_size);
6395 avail = out->kernel_buffer_size;
6396 frames_temp = out->last_fifo_frames_remaining = 0;
6397 }
6398 out->last_fifo_valid = true;
6399 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6400
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006401 if (out->written >= frames_temp)
6402 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006403
Andy Hunga1f48fa2019-07-01 18:14:53 -07006404 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6405 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6406
Weiyin Jiangd4633762018-03-16 12:05:03 +08006407 // This adjustment accounts for buffering after app processor.
6408 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006409 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006410 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006411 if (signed_frames >= frames_temp)
6412 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006413
Weiyin Jiangd4633762018-03-16 12:05:03 +08006414 // Adjustment accounts for A2dp encoder latency with non offload usecases
6415 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006416 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006417 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6418 if (signed_frames >= frames_temp)
6419 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006420 }
6421
6422 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006423 *frames = signed_frames;
6424 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006425 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006426 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6427 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006428 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306429 *frames = out->written;
6430 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306431 if (is_offload_usecase(out->usecase))
6432 ret = -EINVAL;
6433 else
6434 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006435 }
6436 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006437 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006438 return ret;
6439}
6440
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006441static int out_set_callback(struct audio_stream_out *stream,
6442 stream_callback_t callback, void *cookie)
6443{
6444 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006445 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006446
6447 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006448 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006449 out->client_callback = callback;
6450 out->client_cookie = cookie;
6451 if (out->adsp_hdlr_stream_handle) {
6452 ret = audio_extn_adsp_hdlr_stream_set_callback(
6453 out->adsp_hdlr_stream_handle,
6454 callback,
6455 cookie);
6456 if (ret)
6457 ALOGW("%s:adsp hdlr callback registration failed %d",
6458 __func__, ret);
6459 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006460 pthread_mutex_unlock(&out->lock);
6461 return 0;
6462}
6463
6464static int out_pause(struct audio_stream_out* stream)
6465{
6466 struct stream_out *out = (struct stream_out *)stream;
6467 int status = -ENOSYS;
6468 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006469 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006470 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306471 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006472 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006473 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006474 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306475 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306476 status = compress_pause(out->compr);
6477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006478 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006479
Mingming Yin21854652016-04-13 11:54:02 -07006480 if (audio_extn_passthru_is_active()) {
6481 ALOGV("offload use case, pause passthru");
6482 audio_extn_passthru_on_pause(out);
6483 }
6484
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306485 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006486 audio_extn_dts_notify_playback_state(out->usecase, 0,
6487 out->sample_rate, popcount(out->channel_mask),
6488 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006489 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006490 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006491 pthread_mutex_unlock(&out->lock);
6492 }
6493 return status;
6494}
6495
6496static int out_resume(struct audio_stream_out* stream)
6497{
6498 struct stream_out *out = (struct stream_out *)stream;
6499 int status = -ENOSYS;
6500 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006501 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006502 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306503 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006504 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006505 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006506 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306507 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306508 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006509 }
6510 if (!status) {
6511 out->offload_state = OFFLOAD_STATE_PLAYING;
6512 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306513 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006514 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6515 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006516 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006517 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006518 pthread_mutex_unlock(&out->lock);
6519 }
6520 return status;
6521}
6522
6523static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6524{
6525 struct stream_out *out = (struct stream_out *)stream;
6526 int status = -ENOSYS;
6527 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006528 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006529 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006530 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6531 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6532 else
6533 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6534 pthread_mutex_unlock(&out->lock);
6535 }
6536 return status;
6537}
6538
6539static int out_flush(struct audio_stream_out* stream)
6540{
6541 struct stream_out *out = (struct stream_out *)stream;
6542 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006543 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006544 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006545 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006546 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006547 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6548 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006549 } else {
6550 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6551 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006552 out->written = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006553 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006554 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006555 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006556 return 0;
6557 }
6558 return -ENOSYS;
6559}
6560
Haynes Mathew George16081042017-05-31 17:16:49 -07006561static int out_stop(const struct audio_stream_out* stream)
6562{
6563 struct stream_out *out = (struct stream_out *)stream;
6564 struct audio_device *adev = out->dev;
6565 int ret = -ENOSYS;
6566
6567 ALOGV("%s", __func__);
6568 pthread_mutex_lock(&adev->lock);
6569 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6570 out->playback_started && out->pcm != NULL) {
6571 pcm_stop(out->pcm);
6572 ret = stop_output_stream(out);
6573 out->playback_started = false;
6574 }
6575 pthread_mutex_unlock(&adev->lock);
6576 return ret;
6577}
6578
6579static int out_start(const struct audio_stream_out* stream)
6580{
6581 struct stream_out *out = (struct stream_out *)stream;
6582 struct audio_device *adev = out->dev;
6583 int ret = -ENOSYS;
6584
6585 ALOGV("%s", __func__);
6586 pthread_mutex_lock(&adev->lock);
6587 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6588 !out->playback_started && out->pcm != NULL) {
6589 ret = start_output_stream(out);
6590 if (ret == 0) {
6591 out->playback_started = true;
6592 }
6593 }
6594 pthread_mutex_unlock(&adev->lock);
6595 return ret;
6596}
6597
6598/*
6599 * Modify config->period_count based on min_size_frames
6600 */
6601static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6602{
6603 int periodCountRequested = (min_size_frames + config->period_size - 1)
6604 / config->period_size;
6605 int periodCount = MMAP_PERIOD_COUNT_MIN;
6606
6607 ALOGV("%s original config.period_size = %d config.period_count = %d",
6608 __func__, config->period_size, config->period_count);
6609
6610 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6611 periodCount *= 2;
6612 }
6613 config->period_count = periodCount;
6614
6615 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6616}
6617
Phil Burkfe17efd2019-03-25 10:23:35 -07006618// Read offset for the positional timestamp from a persistent vendor property.
6619// This is to workaround apparent inaccuracies in the timing information that
6620// is used by the AAudio timing model. The inaccuracies can cause glitches.
6621static int64_t get_mmap_out_time_offset() {
6622 const int32_t kDefaultOffsetMicros = 0;
6623 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006624 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006625 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6626 return mmap_time_offset_micros * (int64_t)1000;
6627}
6628
Haynes Mathew George16081042017-05-31 17:16:49 -07006629static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6630 int32_t min_size_frames,
6631 struct audio_mmap_buffer_info *info)
6632{
6633 struct stream_out *out = (struct stream_out *)stream;
6634 struct audio_device *adev = out->dev;
6635 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006636 unsigned int offset1 = 0;
6637 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006638 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006639 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006640 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006641
Arun Mirpuri5d170872019-03-26 13:21:31 -07006642 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306643 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006644 pthread_mutex_lock(&adev->lock);
6645
Sharad Sanglec6f32552018-05-04 16:15:38 +05306646 if (CARD_STATUS_OFFLINE == out->card_status ||
6647 CARD_STATUS_OFFLINE == adev->card_status) {
6648 ALOGW("out->card_status or adev->card_status offline, try again");
6649 ret = -EIO;
6650 goto exit;
6651 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306652 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006653 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6654 ret = -EINVAL;
6655 goto exit;
6656 }
6657 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6658 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6659 ret = -ENOSYS;
6660 goto exit;
6661 }
6662 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6663 if (out->pcm_device_id < 0) {
6664 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6665 __func__, out->pcm_device_id, out->usecase);
6666 ret = -EINVAL;
6667 goto exit;
6668 }
6669
6670 adjust_mmap_period_count(&out->config, min_size_frames);
6671
Arun Mirpuri5d170872019-03-26 13:21:31 -07006672 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006673 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6674 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6675 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306676 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306677 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6678 out->card_status = CARD_STATUS_OFFLINE;
6679 adev->card_status = CARD_STATUS_OFFLINE;
6680 ret = -EIO;
6681 goto exit;
6682 }
6683
Haynes Mathew George16081042017-05-31 17:16:49 -07006684 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6685 step = "open";
6686 ret = -ENODEV;
6687 goto exit;
6688 }
6689 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6690 if (ret < 0) {
6691 step = "begin";
6692 goto exit;
6693 }
juyuchen626833d2019-06-04 16:48:02 +08006694
6695 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006696 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006697 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006698 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006699 ret = platform_get_mmap_data_fd(adev->platform,
6700 out->pcm_device_id, 0 /*playback*/,
6701 &info->shared_memory_fd,
6702 &mmap_size);
6703 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006704 // Fall back to non exclusive mode
6705 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6706 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006707 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6708 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6709
Arun Mirpuri5d170872019-03-26 13:21:31 -07006710 if (mmap_size < buffer_size) {
6711 step = "mmap";
6712 goto exit;
6713 }
juyuchen626833d2019-06-04 16:48:02 +08006714 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006715 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006716 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006717 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006718
6719 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6720 if (ret < 0) {
6721 step = "commit";
6722 goto exit;
6723 }
6724
Phil Burkfe17efd2019-03-25 10:23:35 -07006725 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6726
Haynes Mathew George16081042017-05-31 17:16:49 -07006727 out->standby = false;
6728 ret = 0;
6729
Arun Mirpuri5d170872019-03-26 13:21:31 -07006730 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006731 __func__, info->shared_memory_address, info->buffer_size_frames);
6732
6733exit:
6734 if (ret != 0) {
6735 if (out->pcm == NULL) {
6736 ALOGE("%s: %s - %d", __func__, step, ret);
6737 } else {
6738 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6739 pcm_close(out->pcm);
6740 out->pcm = NULL;
6741 }
6742 }
6743 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306744 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006745 return ret;
6746}
6747
6748static int out_get_mmap_position(const struct audio_stream_out *stream,
6749 struct audio_mmap_position *position)
6750{
6751 struct stream_out *out = (struct stream_out *)stream;
6752 ALOGVV("%s", __func__);
6753 if (position == NULL) {
6754 return -EINVAL;
6755 }
6756 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006757 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006758 return -ENOSYS;
6759 }
6760 if (out->pcm == NULL) {
6761 return -ENOSYS;
6762 }
6763
6764 struct timespec ts = { 0, 0 };
6765 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6766 if (ret < 0) {
6767 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6768 return ret;
6769 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006770 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6771 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006772 return 0;
6773}
6774
6775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006776/** audio_stream_in implementation **/
6777static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6778{
6779 struct stream_in *in = (struct stream_in *)stream;
6780
6781 return in->config.rate;
6782}
6783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006784static int in_set_sample_rate(struct audio_stream *stream __unused,
6785 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006786{
6787 return -ENOSYS;
6788}
6789
6790static size_t in_get_buffer_size(const struct audio_stream *stream)
6791{
6792 struct stream_in *in = (struct stream_in *)stream;
6793
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006794 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6795 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006796 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6797 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306798 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306799 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006800
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006801 return in->config.period_size * in->af_period_multiplier *
6802 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006803}
6804
6805static uint32_t in_get_channels(const struct audio_stream *stream)
6806{
6807 struct stream_in *in = (struct stream_in *)stream;
6808
6809 return in->channel_mask;
6810}
6811
6812static audio_format_t in_get_format(const struct audio_stream *stream)
6813{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006814 struct stream_in *in = (struct stream_in *)stream;
6815
6816 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006817}
6818
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006819static int in_set_format(struct audio_stream *stream __unused,
6820 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006821{
6822 return -ENOSYS;
6823}
6824
6825static int in_standby(struct audio_stream *stream)
6826{
6827 struct stream_in *in = (struct stream_in *)stream;
6828 struct audio_device *adev = in->dev;
6829 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306830 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6831 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006832 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306833
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006834 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006835 if (!in->standby && in->is_st_session) {
6836 ALOGD("%s: sound trigger pcm stop lab", __func__);
6837 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006838 if (adev->num_va_sessions > 0)
6839 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006840 in->standby = 1;
6841 }
6842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006843 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006844 if (adev->adm_deregister_stream)
6845 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6846
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006847 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006848 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006849 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006850 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006851 voice_extn_compress_voip_close_input_stream(stream);
6852 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006853 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6854 do_stop = in->capture_started;
6855 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006856 if (in->mmap_shared_memory_fd >= 0) {
6857 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6858 __func__, in->mmap_shared_memory_fd);
6859 close(in->mmap_shared_memory_fd);
6860 in->mmap_shared_memory_fd = -1;
6861 }
Zhou Songa8895042016-07-05 17:54:22 +08006862 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306863 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306864 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006865 }
6866
Arun Mirpuri5d170872019-03-26 13:21:31 -07006867 if (in->pcm) {
6868 ATRACE_BEGIN("pcm_in_close");
6869 pcm_close(in->pcm);
6870 ATRACE_END();
6871 in->pcm = NULL;
6872 }
6873
Carter Hsu2e429db2019-05-14 18:50:52 +08006874 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006875 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006876
George Gao3018ede2019-10-23 13:23:00 -07006877 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6878 if (adev->num_va_sessions > 0)
6879 adev->num_va_sessions--;
6880 }
Quinn Malef6050362019-01-30 15:55:40 -08006881
Eric Laurent150dbfe2013-02-27 14:31:02 -08006882 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006883 }
6884 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006885 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006886 return status;
6887}
6888
Aalique Grahame22e49102018-12-18 14:23:57 -08006889static int in_dump(const struct audio_stream *stream,
6890 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006891{
Aalique Grahame22e49102018-12-18 14:23:57 -08006892 struct stream_in *in = (struct stream_in *)stream;
6893
6894 // We try to get the lock for consistency,
6895 // but it isn't necessary for these variables.
6896 // If we're not in standby, we may be blocked on a read.
6897 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6898 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6899 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6900 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6901
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006902 char buffer[256]; // for statistics formatting
6903 if (in->start_latency_ms.n > 0) {
6904 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6905 dprintf(fd, " Start latency ms: %s\n", buffer);
6906 }
6907
Aalique Grahame22e49102018-12-18 14:23:57 -08006908 if (locked) {
6909 pthread_mutex_unlock(&in->lock);
6910 }
6911
6912 // dump error info
6913 (void)error_log_dump(
6914 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006916 return 0;
6917}
6918
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306919static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6920{
6921 if (!stream || !parms)
6922 return;
6923
6924 struct stream_in *in = (struct stream_in *)stream;
6925 struct audio_device *adev = in->dev;
6926
6927 card_status_t status;
6928 int card;
6929 if (parse_snd_card_status(parms, &card, &status) < 0)
6930 return;
6931
6932 pthread_mutex_lock(&adev->lock);
6933 bool valid_cb = (card == adev->snd_card);
6934 pthread_mutex_unlock(&adev->lock);
6935
6936 if (!valid_cb)
6937 return;
6938
6939 lock_input_stream(in);
6940 if (in->card_status != status)
6941 in->card_status = status;
6942 pthread_mutex_unlock(&in->lock);
6943
6944 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6945 use_case_table[in->usecase],
6946 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6947
6948 // a better solution would be to report error back to AF and let
6949 // it put the stream to standby
6950 if (status == CARD_STATUS_OFFLINE)
6951 in_standby(&in->stream.common);
6952
6953 return;
6954}
6955
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006956int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006957 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006958 audio_source_t source)
6959{
6960 struct audio_device *adev = in->dev;
6961 int ret = 0;
6962
6963 lock_input_stream(in);
6964 pthread_mutex_lock(&adev->lock);
6965
6966 /* no audio source uses val == 0 */
6967 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6968 in->source = source;
6969 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6970 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6971 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6972 (in->config.rate == 8000 || in->config.rate == 16000 ||
6973 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6974 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6975 ret = voice_extn_compress_voip_open_input_stream(in);
6976 if (ret != 0) {
6977 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6978 __func__, ret);
6979 }
6980 }
6981 }
6982
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006983 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6984 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006985 // Workaround: If routing to an non existing usb device, fail gracefully
6986 // The routing request will otherwise block during 10 second
6987 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006988 struct str_parms *usb_addr =
6989 str_parms_create_str(get_usb_device_address(devices));
6990 if (is_usb_in_device_type(devices) && usb_addr &&
6991 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006992 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6993 ret = -ENOSYS;
6994 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006995 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006996 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006997 if (!in->standby && !in->is_st_session) {
6998 ALOGV("update input routing change");
6999 // inform adm before actual routing to prevent glitches.
7000 if (adev->adm_on_routing_change) {
7001 adev->adm_on_routing_change(adev->adm_data,
7002 in->capture_handle);
7003 ret = select_devices(adev, in->usecase);
7004 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7005 adev->adm_routing_changed = true;
7006 }
7007 }
7008 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007009 if (usb_addr)
7010 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007011 }
7012 pthread_mutex_unlock(&adev->lock);
7013 pthread_mutex_unlock(&in->lock);
7014
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007015 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007016 return ret;
7017}
7018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007019static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7020{
7021 struct stream_in *in = (struct stream_in *)stream;
7022 struct audio_device *adev = in->dev;
7023 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007024 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307025 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007026
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307027 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007028 parms = str_parms_create_str(kvpairs);
7029
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307030 if (!parms)
7031 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007032 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007033 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007034
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307035 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7036 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307037 strlcpy(in->profile, value, sizeof(in->profile));
7038 ALOGV("updating stream profile with value '%s'", in->profile);
7039 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7040 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007041 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307042 in->sample_rate, in->bit_width,
7043 in->profile, &in->app_type_cfg);
7044 }
7045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007046 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007047 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007048
7049 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307050error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307051 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007052}
7053
7054static char* in_get_parameters(const struct audio_stream *stream,
7055 const char *keys)
7056{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007057 struct stream_in *in = (struct stream_in *)stream;
7058 struct str_parms *query = str_parms_create_str(keys);
7059 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007060 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007061
7062 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007063 if (reply) {
7064 str_parms_destroy(reply);
7065 }
7066 if (query) {
7067 str_parms_destroy(query);
7068 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007069 ALOGE("in_get_parameters: failed to create query or reply");
7070 return NULL;
7071 }
7072
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007073 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007074
7075 voice_extn_in_get_parameters(in, query, reply);
7076
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007077 stream_get_parameter_channels(query, reply,
7078 &in->supported_channel_masks[0]);
7079 stream_get_parameter_formats(query, reply,
7080 &in->supported_formats[0]);
7081 stream_get_parameter_rates(query, reply,
7082 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007083 str = str_parms_to_str(reply);
7084 str_parms_destroy(query);
7085 str_parms_destroy(reply);
7086
7087 ALOGV("%s: exit: returns - %s", __func__, str);
7088 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089}
7090
Aalique Grahame22e49102018-12-18 14:23:57 -08007091static int in_set_gain(struct audio_stream_in *stream,
7092 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007093{
Aalique Grahame22e49102018-12-18 14:23:57 -08007094 struct stream_in *in = (struct stream_in *)stream;
7095 char mixer_ctl_name[128];
7096 struct mixer_ctl *ctl;
7097 int ctl_value;
7098
7099 ALOGV("%s: gain %f", __func__, gain);
7100
7101 if (stream == NULL)
7102 return -EINVAL;
7103
7104 /* in_set_gain() only used to silence MMAP capture for now */
7105 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7106 return -ENOSYS;
7107
7108 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7109
7110 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7111 if (!ctl) {
7112 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7113 __func__, mixer_ctl_name);
7114 return -ENOSYS;
7115 }
7116
7117 if (gain < RECORD_GAIN_MIN)
7118 gain = RECORD_GAIN_MIN;
7119 else if (gain > RECORD_GAIN_MAX)
7120 gain = RECORD_GAIN_MAX;
7121 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7122
7123 mixer_ctl_set_value(ctl, 0, ctl_value);
7124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125 return 0;
7126}
7127
7128static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7129 size_t bytes)
7130{
7131 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307132
7133 if (in == NULL) {
7134 ALOGE("%s: stream_in ptr is NULL", __func__);
7135 return -EINVAL;
7136 }
7137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307139 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307140 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007141
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007142 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307143
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007144 if (in->is_st_session) {
7145 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7146 /* Read from sound trigger HAL */
7147 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007148 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007149 if (adev->num_va_sessions < UINT_MAX)
7150 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007151 in->standby = 0;
7152 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007153 pthread_mutex_unlock(&in->lock);
7154 return bytes;
7155 }
7156
Haynes Mathew George16081042017-05-31 17:16:49 -07007157 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7158 ret = -ENOSYS;
7159 goto exit;
7160 }
7161
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007162 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7163 !in->standby && adev->adm_routing_changed) {
7164 ret = -ENOSYS;
7165 goto exit;
7166 }
7167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007169 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7170
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007171 pthread_mutex_lock(&adev->lock);
7172 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7173 ret = voice_extn_compress_voip_start_input_stream(in);
7174 else
7175 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007176 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7177 if (adev->num_va_sessions < UINT_MAX)
7178 adev->num_va_sessions++;
7179 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007180 pthread_mutex_unlock(&adev->lock);
7181 if (ret != 0) {
7182 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007183 }
7184 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007185
7186 // log startup time in ms.
7187 simple_stats_log(
7188 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007190
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307191 /* Avoid read if capture_stopped is set */
7192 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7193 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7194 ret = -EINVAL;
7195 goto exit;
7196 }
7197
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007198 // what's the duration requested by the client?
7199 long ns = 0;
7200
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307201 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007202 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7203 in->config.rate;
7204
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007205 ret = request_in_focus(in, ns);
7206 if (ret != 0)
7207 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007208 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007209
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307210 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307211 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7212 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307213 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007214 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307215 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007216 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007217 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007218 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007219 } else if (audio_extn_ffv_get_stream() == in) {
7220 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307221 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007222 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307223 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7224 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7225 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7226 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307227 ret = -EINVAL;
7228 goto exit;
7229 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307230 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307231 ret = -errno;
7232 }
7233 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307234 /* bytes read is always set to bytes for non compress usecases */
7235 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236 }
7237
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007238 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007240 /*
Quinn Malef6050362019-01-30 15:55:40 -08007241 * Instead of writing zeroes here, we could trust the hardware to always
7242 * provide zeroes when muted. This is also muted with voice recognition
7243 * usecases so that other clients do not have access to voice recognition
7244 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245 */
Quinn Malef6050362019-01-30 15:55:40 -08007246 if ((ret == 0 && voice_get_mic_mute(adev) &&
7247 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007248 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7249 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007250 (adev->num_va_sessions &&
7251 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7252 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7253 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007254 memset(buffer, 0, bytes);
7255
7256exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307257 frame_size = audio_stream_in_frame_size(stream);
7258 if (frame_size > 0)
7259 in->frames_read += bytes_read/frame_size;
7260
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007261 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307262 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007263 pthread_mutex_unlock(&in->lock);
7264
7265 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307266 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307267 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307268 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307269 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307270 in->standby = true;
7271 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307272 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307273 bytes_read = bytes;
7274 memset(buffer, 0, bytes);
7275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007276 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007277 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7278 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007279 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307280 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307281 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007282 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307283 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007284}
7285
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007286static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007287{
7288 return 0;
7289}
7290
Aalique Grahame22e49102018-12-18 14:23:57 -08007291static int in_get_capture_position(const struct audio_stream_in *stream,
7292 int64_t *frames, int64_t *time)
7293{
7294 if (stream == NULL || frames == NULL || time == NULL) {
7295 return -EINVAL;
7296 }
7297 struct stream_in *in = (struct stream_in *)stream;
7298 int ret = -ENOSYS;
7299
7300 lock_input_stream(in);
7301 // note: ST sessions do not close the alsa pcm driver synchronously
7302 // on standby. Therefore, we may return an error even though the
7303 // pcm stream is still opened.
7304 if (in->standby) {
7305 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7306 "%s stream in standby but pcm not NULL for non ST session", __func__);
7307 goto exit;
7308 }
7309 if (in->pcm) {
7310 struct timespec timestamp;
7311 unsigned int avail;
7312 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7313 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007314 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007315 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007316 ret = 0;
7317 }
7318 }
7319exit:
7320 pthread_mutex_unlock(&in->lock);
7321 return ret;
7322}
7323
Carter Hsu2e429db2019-05-14 18:50:52 +08007324static int in_update_effect_list(bool add, effect_handle_t effect,
7325 struct listnode *head)
7326{
7327 struct listnode *node;
7328 struct in_effect_list *elist = NULL;
7329 struct in_effect_list *target = NULL;
7330 int ret = 0;
7331
7332 if (!head)
7333 return ret;
7334
7335 list_for_each(node, head) {
7336 elist = node_to_item(node, struct in_effect_list, list);
7337 if (elist->handle == effect) {
7338 target = elist;
7339 break;
7340 }
7341 }
7342
7343 if (add) {
7344 if (target) {
7345 ALOGD("effect %p already exist", effect);
7346 return ret;
7347 }
7348
7349 target = (struct in_effect_list *)
7350 calloc(1, sizeof(struct in_effect_list));
7351
7352 if (!target) {
7353 ALOGE("%s:fail to allocate memory", __func__);
7354 return -ENOMEM;
7355 }
7356
7357 target->handle = effect;
7358 list_add_tail(head, &target->list);
7359 } else {
7360 if (target) {
7361 list_remove(&target->list);
7362 free(target);
7363 }
7364 }
7365
7366 return ret;
7367}
7368
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007369static int add_remove_audio_effect(const struct audio_stream *stream,
7370 effect_handle_t effect,
7371 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007372{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007373 struct stream_in *in = (struct stream_in *)stream;
7374 int status = 0;
7375 effect_descriptor_t desc;
7376
7377 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007378 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7379
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007380 if (status != 0)
7381 return status;
7382
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007383 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007384 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007385 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007386 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7387 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007388 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007389
7390 in_update_effect_list(enable, effect, &in->aec_list);
7391 enable = !list_empty(&in->aec_list);
7392 if (enable == in->enable_aec)
7393 goto exit;
7394
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007395 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007396 ALOGD("AEC enable %d", enable);
7397
Aalique Grahame22e49102018-12-18 14:23:57 -08007398 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7399 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7400 in->dev->enable_voicerx = enable;
7401 struct audio_usecase *usecase;
7402 struct listnode *node;
7403 list_for_each(node, &in->dev->usecase_list) {
7404 usecase = node_to_item(node, struct audio_usecase, list);
7405 if (usecase->type == PCM_PLAYBACK)
7406 select_devices(in->dev, usecase->id);
7407 }
7408 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007409 if (!in->standby) {
7410 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7411 select_devices(in->dev, in->usecase);
7412 }
7413
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007414 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007415 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7416
7417 in_update_effect_list(enable, effect, &in->ns_list);
7418 enable = !list_empty(&in->ns_list);
7419 if (enable == in->enable_ns)
7420 goto exit;
7421
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007422 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007423 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007424 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007425 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7426 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007427 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7428 select_devices(in->dev, in->usecase);
7429 } else
7430 select_devices(in->dev, in->usecase);
7431 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007432 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007433exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007434 pthread_mutex_unlock(&in->dev->lock);
7435 pthread_mutex_unlock(&in->lock);
7436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007437 return 0;
7438}
7439
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007440static int in_add_audio_effect(const struct audio_stream *stream,
7441 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007442{
Eric Laurent994a6932013-07-17 11:51:42 -07007443 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007444 return add_remove_audio_effect(stream, effect, true);
7445}
7446
7447static int in_remove_audio_effect(const struct audio_stream *stream,
7448 effect_handle_t effect)
7449{
Eric Laurent994a6932013-07-17 11:51:42 -07007450 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007451 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007452}
7453
Derek Chenf939fb72018-11-13 13:34:41 -08007454streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7455 audio_io_handle_t input)
7456{
7457 struct listnode *node;
7458
7459 list_for_each(node, &dev->active_inputs_list) {
7460 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7461 streams_input_ctxt_t,
7462 list);
7463 if (in_ctxt->input->capture_handle == input) {
7464 return in_ctxt;
7465 }
7466 }
7467 return NULL;
7468}
7469
7470streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7471 audio_io_handle_t output)
7472{
7473 struct listnode *node;
7474
7475 list_for_each(node, &dev->active_outputs_list) {
7476 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7477 streams_output_ctxt_t,
7478 list);
7479 if (out_ctxt->output->handle == output) {
7480 return out_ctxt;
7481 }
7482 }
7483 return NULL;
7484}
7485
Haynes Mathew George16081042017-05-31 17:16:49 -07007486static int in_stop(const struct audio_stream_in* stream)
7487{
7488 struct stream_in *in = (struct stream_in *)stream;
7489 struct audio_device *adev = in->dev;
7490
7491 int ret = -ENOSYS;
7492 ALOGV("%s", __func__);
7493 pthread_mutex_lock(&adev->lock);
7494 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7495 in->capture_started && in->pcm != NULL) {
7496 pcm_stop(in->pcm);
7497 ret = stop_input_stream(in);
7498 in->capture_started = false;
7499 }
7500 pthread_mutex_unlock(&adev->lock);
7501 return ret;
7502}
7503
7504static int in_start(const struct audio_stream_in* stream)
7505{
7506 struct stream_in *in = (struct stream_in *)stream;
7507 struct audio_device *adev = in->dev;
7508 int ret = -ENOSYS;
7509
7510 ALOGV("%s in %p", __func__, in);
7511 pthread_mutex_lock(&adev->lock);
7512 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7513 !in->capture_started && in->pcm != NULL) {
7514 if (!in->capture_started) {
7515 ret = start_input_stream(in);
7516 if (ret == 0) {
7517 in->capture_started = true;
7518 }
7519 }
7520 }
7521 pthread_mutex_unlock(&adev->lock);
7522 return ret;
7523}
7524
Phil Burke0a86d12019-02-16 22:28:11 -08007525// Read offset for the positional timestamp from a persistent vendor property.
7526// This is to workaround apparent inaccuracies in the timing information that
7527// is used by the AAudio timing model. The inaccuracies can cause glitches.
7528static int64_t in_get_mmap_time_offset() {
7529 const int32_t kDefaultOffsetMicros = 0;
7530 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007531 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007532 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7533 return mmap_time_offset_micros * (int64_t)1000;
7534}
7535
Haynes Mathew George16081042017-05-31 17:16:49 -07007536static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7537 int32_t min_size_frames,
7538 struct audio_mmap_buffer_info *info)
7539{
7540 struct stream_in *in = (struct stream_in *)stream;
7541 struct audio_device *adev = in->dev;
7542 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007543 unsigned int offset1 = 0;
7544 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007545 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007546 uint32_t mmap_size = 0;
7547 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007548
7549 pthread_mutex_lock(&adev->lock);
7550 ALOGV("%s in %p", __func__, in);
7551
Sharad Sanglec6f32552018-05-04 16:15:38 +05307552 if (CARD_STATUS_OFFLINE == in->card_status||
7553 CARD_STATUS_OFFLINE == adev->card_status) {
7554 ALOGW("in->card_status or adev->card_status offline, try again");
7555 ret = -EIO;
7556 goto exit;
7557 }
7558
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307559 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007560 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7561 ret = -EINVAL;
7562 goto exit;
7563 }
7564 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7565 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7566 ALOGV("%s in %p", __func__, in);
7567 ret = -ENOSYS;
7568 goto exit;
7569 }
7570 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7571 if (in->pcm_device_id < 0) {
7572 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7573 __func__, in->pcm_device_id, in->usecase);
7574 ret = -EINVAL;
7575 goto exit;
7576 }
7577
7578 adjust_mmap_period_count(&in->config, min_size_frames);
7579
7580 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7581 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7582 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7583 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307584 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307585 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7586 in->card_status = CARD_STATUS_OFFLINE;
7587 adev->card_status = CARD_STATUS_OFFLINE;
7588 ret = -EIO;
7589 goto exit;
7590 }
7591
Haynes Mathew George16081042017-05-31 17:16:49 -07007592 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7593 step = "open";
7594 ret = -ENODEV;
7595 goto exit;
7596 }
7597
7598 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7599 if (ret < 0) {
7600 step = "begin";
7601 goto exit;
7602 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007603
juyuchen626833d2019-06-04 16:48:02 +08007604 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007605 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7606 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7607 info->burst_size_frames = in->config.period_size;
7608 ret = platform_get_mmap_data_fd(adev->platform,
7609 in->pcm_device_id, 1 /*capture*/,
7610 &info->shared_memory_fd,
7611 &mmap_size);
7612 if (ret < 0) {
7613 // Fall back to non exclusive mode
7614 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7615 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007616 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7617 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7618
Arun Mirpuri5d170872019-03-26 13:21:31 -07007619 if (mmap_size < buffer_size) {
7620 step = "mmap";
7621 goto exit;
7622 }
juyuchen626833d2019-06-04 16:48:02 +08007623 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007624 }
7625
7626 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007627
7628 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7629 if (ret < 0) {
7630 step = "commit";
7631 goto exit;
7632 }
7633
Phil Burke0a86d12019-02-16 22:28:11 -08007634 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7635
Haynes Mathew George16081042017-05-31 17:16:49 -07007636 in->standby = false;
7637 ret = 0;
7638
7639 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7640 __func__, info->shared_memory_address, info->buffer_size_frames);
7641
7642exit:
7643 if (ret != 0) {
7644 if (in->pcm == NULL) {
7645 ALOGE("%s: %s - %d", __func__, step, ret);
7646 } else {
7647 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7648 pcm_close(in->pcm);
7649 in->pcm = NULL;
7650 }
7651 }
7652 pthread_mutex_unlock(&adev->lock);
7653 return ret;
7654}
7655
7656static int in_get_mmap_position(const struct audio_stream_in *stream,
7657 struct audio_mmap_position *position)
7658{
7659 struct stream_in *in = (struct stream_in *)stream;
7660 ALOGVV("%s", __func__);
7661 if (position == NULL) {
7662 return -EINVAL;
7663 }
7664 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7665 return -ENOSYS;
7666 }
7667 if (in->pcm == NULL) {
7668 return -ENOSYS;
7669 }
7670 struct timespec ts = { 0, 0 };
7671 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7672 if (ret < 0) {
7673 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7674 return ret;
7675 }
Phil Burke0a86d12019-02-16 22:28:11 -08007676 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7677 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007678 return 0;
7679}
7680
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307681static int in_get_active_microphones(const struct audio_stream_in *stream,
7682 struct audio_microphone_characteristic_t *mic_array,
7683 size_t *mic_count) {
7684 struct stream_in *in = (struct stream_in *)stream;
7685 struct audio_device *adev = in->dev;
7686 ALOGVV("%s", __func__);
7687
7688 lock_input_stream(in);
7689 pthread_mutex_lock(&adev->lock);
7690 int ret = platform_get_active_microphones(adev->platform,
7691 audio_channel_count_from_in_mask(in->channel_mask),
7692 in->usecase, mic_array, mic_count);
7693 pthread_mutex_unlock(&adev->lock);
7694 pthread_mutex_unlock(&in->lock);
7695
7696 return ret;
7697}
7698
7699static int adev_get_microphones(const struct audio_hw_device *dev,
7700 struct audio_microphone_characteristic_t *mic_array,
7701 size_t *mic_count) {
7702 struct audio_device *adev = (struct audio_device *)dev;
7703 ALOGVV("%s", __func__);
7704
7705 pthread_mutex_lock(&adev->lock);
7706 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7707 pthread_mutex_unlock(&adev->lock);
7708
7709 return ret;
7710}
juyuchendb308c22019-01-21 11:57:17 -07007711
7712static void in_update_sink_metadata(struct audio_stream_in *stream,
7713 const struct sink_metadata *sink_metadata) {
7714
7715 if (stream == NULL
7716 || sink_metadata == NULL
7717 || sink_metadata->tracks == NULL) {
7718 return;
7719 }
7720
7721 int error = 0;
7722 struct stream_in *in = (struct stream_in *)stream;
7723 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007724 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007725 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007726
7727 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007728
7729 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007730 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007731
7732 lock_input_stream(in);
7733 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007734 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007735
Zhou Song62ea0282020-03-22 19:53:01 +08007736 is_ha_usecase = adev->ha_proxy_enable ?
7737 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7738 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7739 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007740 && adev->voice_tx_output != NULL) {
7741 /* Use the rx device from afe-proxy record to route voice call because
7742 there is no routing if tx device is on primary hal and rx device
7743 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007744 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007745
7746 if (!voice_is_call_state_active(adev)) {
7747 if (adev->mode == AUDIO_MODE_IN_CALL) {
7748 adev->current_call_output = adev->voice_tx_output;
7749 error = voice_start_call(adev);
7750 if (error != 0)
7751 ALOGE("%s: start voice call failed %d", __func__, error);
7752 }
7753 } else {
7754 adev->current_call_output = adev->voice_tx_output;
7755 voice_update_devices_for_all_voice_usecases(adev);
7756 }
7757 }
7758
7759 pthread_mutex_unlock(&adev->lock);
7760 pthread_mutex_unlock(&in->lock);
7761}
7762
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307763int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007764 audio_io_handle_t handle,
7765 audio_devices_t devices,
7766 audio_output_flags_t flags,
7767 struct audio_config *config,
7768 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007769 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007770{
7771 struct audio_device *adev = (struct audio_device *)dev;
7772 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307773 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007774 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007775 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307776 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007777 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7778 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7779 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7780 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007781 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007782 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7783 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007784 bool force_haptic_path =
7785 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007786 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007787#ifdef AUDIO_GKI_ENABLED
7788 __s32 *generic_dec;
7789#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007790
kunleizdff872d2018-08-20 14:40:33 +08007791 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007792 is_usb_dev = false;
7793 devices = AUDIO_DEVICE_OUT_SPEAKER;
7794 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7795 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007796 if (config->format == AUDIO_FORMAT_DEFAULT)
7797 config->format = AUDIO_FORMAT_PCM_16_BIT;
7798 if (config->sample_rate == 0)
7799 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7800 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7801 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007802 }
7803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007804 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307805
Rahul Sharma99770982019-03-06 17:05:26 +05307806 pthread_mutex_lock(&adev->lock);
7807 if (out_get_stream(adev, handle) != NULL) {
7808 ALOGW("%s, output stream already opened", __func__);
7809 ret = -EEXIST;
7810 }
7811 pthread_mutex_unlock(&adev->lock);
7812 if (ret)
7813 return ret;
7814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007815 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7816
Mingming Yin3a941d42016-02-17 18:08:05 -08007817 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007818 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7819 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307820
7821
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007822 if (!out) {
7823 return -ENOMEM;
7824 }
7825
Haynes Mathew George204045b2015-02-25 20:32:03 -08007826 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007827 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007828 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007829 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007830 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007832 if (devices == AUDIO_DEVICE_NONE)
7833 devices = AUDIO_DEVICE_OUT_SPEAKER;
7834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007835 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007836 list_init(&out->device_list);
7837 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007838 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007839 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007840 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307841 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307842 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7843 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7844 else
7845 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007846 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007847 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007848 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307849 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307850 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307851 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007852 out->hal_output_suspend_supported = 0;
7853 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307854 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307855 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307856 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007857 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007858
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307859 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307860 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007861 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7862
Aalique Grahame22e49102018-12-18 14:23:57 -08007863 if (direct_dev &&
7864 (audio_is_linear_pcm(out->format) ||
7865 config->format == AUDIO_FORMAT_DEFAULT) &&
7866 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7867 audio_format_t req_format = config->format;
7868 audio_channel_mask_t req_channel_mask = config->channel_mask;
7869 uint32_t req_sample_rate = config->sample_rate;
7870
7871 pthread_mutex_lock(&adev->lock);
7872 if (is_hdmi) {
7873 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7874 ret = read_hdmi_sink_caps(out);
7875 if (config->sample_rate == 0)
7876 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7877 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7878 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7879 if (config->format == AUDIO_FORMAT_DEFAULT)
7880 config->format = AUDIO_FORMAT_PCM_16_BIT;
7881 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007882 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7883 &config->format,
7884 &out->supported_formats[0],
7885 MAX_SUPPORTED_FORMATS,
7886 &config->channel_mask,
7887 &out->supported_channel_masks[0],
7888 MAX_SUPPORTED_CHANNEL_MASKS,
7889 &config->sample_rate,
7890 &out->supported_sample_rates[0],
7891 MAX_SUPPORTED_SAMPLE_RATES);
7892 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007893 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007894
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007895 pthread_mutex_unlock(&adev->lock);
7896 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007897 if (ret == -ENOSYS) {
7898 /* ignore and go with default */
7899 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007900 }
7901 // For MMAP NO IRQ, allow conversions in ADSP
7902 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7903 goto error_open;
7904 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007905 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007906 goto error_open;
7907 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007908
7909 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7910 config->sample_rate = req_sample_rate;
7911 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7912 config->channel_mask = req_channel_mask;
7913 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7914 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007915 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007916
7917 out->sample_rate = config->sample_rate;
7918 out->channel_mask = config->channel_mask;
7919 out->format = config->format;
7920 if (is_hdmi) {
7921 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7922 out->config = pcm_config_hdmi_multi;
7923 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7924 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7925 out->config = pcm_config_mmap_playback;
7926 out->stream.start = out_start;
7927 out->stream.stop = out_stop;
7928 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7929 out->stream.get_mmap_position = out_get_mmap_position;
7930 } else {
7931 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7932 out->config = pcm_config_hifi;
7933 }
7934
7935 out->config.rate = out->sample_rate;
7936 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7937 if (is_hdmi) {
7938 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7939 audio_bytes_per_sample(out->format));
7940 }
7941 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007942 }
7943
Derek Chenf6318be2017-06-12 17:16:24 -04007944 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007945 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007946 /* extract car audio stream index */
7947 out->car_audio_stream =
7948 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7949 if (out->car_audio_stream < 0) {
7950 ALOGE("%s: invalid car audio stream %x",
7951 __func__, out->car_audio_stream);
7952 ret = -EINVAL;
7953 goto error_open;
7954 }
Derek Chen5f67a942020-02-24 23:08:13 -08007955 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007956 }
7957
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007958 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007959 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007960 if (!voice_extn_is_compress_voip_supported()) {
7961 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7962 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007963 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307964 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007965 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7966 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007967 out->volume_l = INVALID_OUT_VOLUME;
7968 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007969
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007970 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007971 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007972 uint32_t channel_count =
7973 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307974 out->config.channels = channel_count;
7975
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007976 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7977 out->sample_rate, out->format,
7978 channel_count, false);
7979 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7980 if (frame_size != 0)
7981 out->config.period_size = buffer_size / frame_size;
7982 else
7983 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007984 }
7985 } else {
7986 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7987 voice_extn_compress_voip_is_active(out->dev)) &&
7988 (voice_extn_compress_voip_is_config_supported(config))) {
7989 ret = voice_extn_compress_voip_open_output_stream(out);
7990 if (ret != 0) {
7991 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7992 __func__, ret);
7993 goto error_open;
7994 }
Sujin Panicker19027262019-09-16 18:28:06 +05307995 } else {
7996 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7997 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007998 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007999 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008000 } else if (audio_is_linear_pcm(out->format) &&
8001 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8002 out->channel_mask = config->channel_mask;
8003 out->sample_rate = config->sample_rate;
8004 out->format = config->format;
8005 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8006 // does this change?
8007 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8008 out->config.rate = config->sample_rate;
8009 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8010 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8011 audio_bytes_per_sample(config->format));
8012 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008013 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308014 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308015 pthread_mutex_lock(&adev->lock);
8016 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8017 pthread_mutex_unlock(&adev->lock);
8018
8019 // reject offload during card offline to allow
8020 // fallback to s/w paths
8021 if (offline) {
8022 ret = -ENODEV;
8023 goto error_open;
8024 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008026 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8027 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8028 ALOGE("%s: Unsupported Offload information", __func__);
8029 ret = -EINVAL;
8030 goto error_open;
8031 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008032
Atul Khare3fa6e542017-08-09 00:56:17 +05308033 if (config->offload_info.format == 0)
8034 config->offload_info.format = config->format;
8035 if (config->offload_info.sample_rate == 0)
8036 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008037
Mingming Yin90310102013-11-13 16:57:00 -08008038 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308039 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008040 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008041 ret = -EINVAL;
8042 goto error_open;
8043 }
8044
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008045 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8046 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8047 (audio_extn_passthru_is_passthrough_stream(out)) &&
8048 !((config->sample_rate == 48000) ||
8049 (config->sample_rate == 96000) ||
8050 (config->sample_rate == 192000))) {
8051 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8052 __func__, config->sample_rate, config->offload_info.format);
8053 ret = -EINVAL;
8054 goto error_open;
8055 }
8056
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008057 out->compr_config.codec = (struct snd_codec *)
8058 calloc(1, sizeof(struct snd_codec));
8059
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008060 if (!out->compr_config.codec) {
8061 ret = -ENOMEM;
8062 goto error_open;
8063 }
8064
Dhananjay Kumarac341582017-02-23 23:42:25 +05308065 out->stream.pause = out_pause;
8066 out->stream.resume = out_resume;
8067 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308068 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308069 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008070 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308071 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008072 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308073 } else {
8074 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8075 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008076 }
vivek mehta446c3962015-09-14 10:57:35 -07008077
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308078 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8079 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008080#ifdef AUDIO_GKI_ENABLED
8081 /* out->compr_config.codec->reserved[1] is for flags */
8082 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8083#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308084 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008085#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308086 }
8087
vivek mehta446c3962015-09-14 10:57:35 -07008088 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008089 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008090 config->format == 0 && config->sample_rate == 0 &&
8091 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008092 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008093 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8094 } else {
8095 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8096 ret = -EEXIST;
8097 goto error_open;
8098 }
vivek mehta446c3962015-09-14 10:57:35 -07008099 }
8100
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008101 if (config->offload_info.channel_mask)
8102 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008103 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008104 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008105 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008106 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308107 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008108 ret = -EINVAL;
8109 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008110 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008111
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008112 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008113 out->sample_rate = config->offload_info.sample_rate;
8114
Mingming Yin3ee55c62014-08-04 14:23:35 -07008115 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008116
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308117 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308118 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308119 audio_extn_dolby_send_ddp_endp_params(adev);
8120 audio_extn_dolby_set_dmid(adev);
8121 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008122
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008123 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008124 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008125 out->compr_config.codec->bit_rate =
8126 config->offload_info.bit_rate;
8127 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308128 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008129 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308130 /* Update bit width only for non passthrough usecases.
8131 * For passthrough usecases, the output will always be opened @16 bit
8132 */
8133 if (!audio_extn_passthru_is_passthrough_stream(out))
8134 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308135
8136 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008137#ifdef AUDIO_GKI_ENABLED
8138 /* out->compr_config.codec->reserved[1] is for flags */
8139 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8140 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8141#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308142 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8143 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008144#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308145
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008146 /*TODO: Do we need to change it for passthrough */
8147 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008148
Manish Dewangana6fc5442015-08-24 20:30:31 +05308149 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8150 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308151 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308152 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308153 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8154 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308155
8156 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8157 AUDIO_FORMAT_PCM) {
8158
8159 /*Based on platform support, configure appropriate alsa format for corresponding
8160 *hal input format.
8161 */
8162 out->compr_config.codec->format = hal_format_to_alsa(
8163 config->offload_info.format);
8164
Ashish Jain83a6cc22016-06-28 14:34:17 +05308165 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308166 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308167 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308168
Dhananjay Kumarac341582017-02-23 23:42:25 +05308169 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308170 *hal input format and alsa format might differ based on platform support.
8171 */
8172 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308173 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308174
8175 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8176
Deeraj Soman93155a62019-09-30 19:00:37 +05308177 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8178 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8179 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8180 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8181 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308182
Ashish Jainf1eaa582016-05-23 20:54:24 +05308183 /* Check if alsa session is configured with the same format as HAL input format,
8184 * if not then derive correct fragment size needed to accomodate the
8185 * conversion of HAL input format to alsa format.
8186 */
8187 audio_extn_utils_update_direct_pcm_fragment_size(out);
8188
8189 /*if hal input and output fragment size is different this indicates HAL input format is
8190 *not same as the alsa format
8191 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308192 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308193 /*Allocate a buffer to convert input data to the alsa configured format.
8194 *size of convert buffer is equal to the size required to hold one fragment size
8195 *worth of pcm data, this is because flinger does not write more than fragment_size
8196 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308197 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8198 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308199 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8200 ret = -ENOMEM;
8201 goto error_open;
8202 }
8203 }
8204 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8205 out->compr_config.fragment_size =
8206 audio_extn_passthru_get_buffer_size(&config->offload_info);
8207 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8208 } else {
8209 out->compr_config.fragment_size =
8210 platform_get_compress_offload_buffer_size(&config->offload_info);
8211 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8212 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008213
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308214 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8215 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8216 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008217 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8218#ifdef AUDIO_GKI_ENABLED
8219 generic_dec =
8220 &(out->compr_config.codec->options.generic.reserved[1]);
8221 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8222 AUDIO_OUTPUT_BIT_WIDTH;
8223#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308224 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008225#endif
8226 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008227
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308228 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8229 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8230 }
8231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008232 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8233 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008234
Manish Dewangan69426c82017-01-30 17:35:36 +05308235 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8236 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8237 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8238 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8239 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8240 } else {
8241 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8242 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008243
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308244 memset(&out->channel_map_param, 0,
8245 sizeof(struct audio_out_channel_map_param));
8246
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008247 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308248 out->send_next_track_params = false;
8249 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008250 out->offload_state = OFFLOAD_STATE_IDLE;
8251 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008252 out->writeAt.tv_sec = 0;
8253 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008254
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008255 audio_extn_dts_create_state_notifier_node(out->usecase);
8256
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008257 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8258 __func__, config->offload_info.version,
8259 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308260
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308261 /* Check if DSD audio format is supported in codec
8262 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308263 */
8264
8265 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308266 (!platform_check_codec_dsd_support(adev->platform) ||
8267 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308268 ret = -EINVAL;
8269 goto error_open;
8270 }
8271
Ashish Jain5106d362016-05-11 19:23:33 +05308272 /* Disable gapless if any of the following is true
8273 * passthrough playback
8274 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308275 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308276 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308277 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308278 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008279 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308280 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308281 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308282 check_and_set_gapless_mode(adev, false);
8283 } else
8284 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008285
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308286 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008287 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8288 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308289 if (config->format == AUDIO_FORMAT_DSD) {
8290 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008291#ifdef AUDIO_GKI_ENABLED
8292 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8293 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8294#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308295 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008296#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308297 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008298
8299 create_offload_callback_thread(out);
8300
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008301 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008302 switch (config->sample_rate) {
8303 case 0:
8304 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8305 break;
8306 case 8000:
8307 case 16000:
8308 case 48000:
8309 out->sample_rate = config->sample_rate;
8310 break;
8311 default:
8312 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8313 config->sample_rate);
8314 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8315 ret = -EINVAL;
8316 goto error_open;
8317 }
8318 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8319 switch (config->channel_mask) {
8320 case AUDIO_CHANNEL_NONE:
8321 case AUDIO_CHANNEL_OUT_STEREO:
8322 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8323 break;
8324 default:
8325 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8326 config->channel_mask);
8327 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8328 ret = -EINVAL;
8329 goto error_open;
8330 }
8331 switch (config->format) {
8332 case AUDIO_FORMAT_DEFAULT:
8333 case AUDIO_FORMAT_PCM_16_BIT:
8334 out->format = AUDIO_FORMAT_PCM_16_BIT;
8335 break;
8336 default:
8337 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8338 config->format);
8339 config->format = AUDIO_FORMAT_PCM_16_BIT;
8340 ret = -EINVAL;
8341 goto error_open;
8342 }
8343
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308344 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008345 if (ret != 0) {
8346 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008347 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008348 goto error_open;
8349 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008350 } else if (is_single_device_type_equal(&out->device_list,
8351 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008352 switch (config->sample_rate) {
8353 case 0:
8354 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8355 break;
8356 case 8000:
8357 case 16000:
8358 case 48000:
8359 out->sample_rate = config->sample_rate;
8360 break;
8361 default:
8362 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8363 config->sample_rate);
8364 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8365 ret = -EINVAL;
8366 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008367 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008368 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8369 switch (config->channel_mask) {
8370 case AUDIO_CHANNEL_NONE:
8371 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8372 break;
8373 case AUDIO_CHANNEL_OUT_STEREO:
8374 out->channel_mask = config->channel_mask;
8375 break;
8376 default:
8377 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8378 config->channel_mask);
8379 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8380 ret = -EINVAL;
8381 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008382 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008383 switch (config->format) {
8384 case AUDIO_FORMAT_DEFAULT:
8385 out->format = AUDIO_FORMAT_PCM_16_BIT;
8386 break;
8387 case AUDIO_FORMAT_PCM_16_BIT:
8388 out->format = config->format;
8389 break;
8390 default:
8391 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8392 config->format);
8393 config->format = AUDIO_FORMAT_PCM_16_BIT;
8394 ret = -EINVAL;
8395 break;
8396 }
8397 if (ret != 0)
8398 goto error_open;
8399
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008400 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8401 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008402 out->config.rate = out->sample_rate;
8403 out->config.channels =
8404 audio_channel_count_from_out_mask(out->channel_mask);
8405 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008406 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008407 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308408 unsigned int channels = 0;
8409 /*Update config params to default if not set by the caller*/
8410 if (config->sample_rate == 0)
8411 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8412 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8413 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8414 if (config->format == AUDIO_FORMAT_DEFAULT)
8415 config->format = AUDIO_FORMAT_PCM_16_BIT;
8416
8417 channels = audio_channel_count_from_out_mask(out->channel_mask);
8418
Varun Balaraje49253e2017-07-06 19:48:56 +05308419 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8420 out->usecase = get_interactive_usecase(adev);
8421 out->config = pcm_config_low_latency;
8422 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308423 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008424 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8425 out->flags);
8426 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008427 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8428 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8429 out->config = pcm_config_mmap_playback;
8430 out->stream.start = out_start;
8431 out->stream.stop = out_stop;
8432 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8433 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308434 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8435 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008436 out->hal_output_suspend_supported =
8437 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8438 out->dynamic_pm_qos_config_supported =
8439 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8440 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008441 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8442 } else {
8443 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8444 //the mixer path will be a string similar to "low-latency-playback resume"
8445 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8446 strlcat(out->pm_qos_mixer_path,
8447 " resume", MAX_MIXER_PATH_LEN);
8448 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8449 out->pm_qos_mixer_path);
8450 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308451 out->config = pcm_config_low_latency;
8452 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8453 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8454 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308455 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8456 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8457 if (out->config.period_size <= 0) {
8458 ALOGE("Invalid configuration period size is not valid");
8459 ret = -EINVAL;
8460 goto error_open;
8461 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008462 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8463 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8464 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008465 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8466 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8467 out->config = pcm_config_haptics_audio;
8468 if (force_haptic_path)
8469 adev->haptics_config = pcm_config_haptics_audio;
8470 else
8471 adev->haptics_config = pcm_config_haptics;
8472
Meng Wangd08ce322020-04-02 08:59:20 +08008473 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008474 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8475
8476 if (force_haptic_path) {
8477 out->config.channels = 1;
8478 adev->haptics_config.channels = 1;
8479 } else
8480 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008481 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008482 ret = audio_extn_auto_hal_open_output_stream(out);
8483 if (ret) {
8484 ALOGE("%s: Failed to open output stream for bus device", __func__);
8485 ret = -EINVAL;
8486 goto error_open;
8487 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308488 } else {
8489 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008490 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8491 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308492 }
8493 out->hal_ip_format = format = out->format;
8494 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8495 out->hal_op_format = pcm_format_to_hal(out->config.format);
8496 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8497 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008498 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308499 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308500 if (out->hal_ip_format != out->hal_op_format) {
8501 uint32_t buffer_size = out->config.period_size *
8502 format_to_bitwidth_table[out->hal_op_format] *
8503 out->config.channels;
8504 out->convert_buffer = calloc(1, buffer_size);
8505 if (out->convert_buffer == NULL){
8506 ALOGE("Allocation failed for convert buffer for size %d",
8507 out->compr_config.fragment_size);
8508 ret = -ENOMEM;
8509 goto error_open;
8510 }
8511 ALOGD("Convert buffer allocated of size %d", buffer_size);
8512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008513 }
8514
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008515 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8516 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308517
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008518 /* TODO remove this hardcoding and check why width is zero*/
8519 if (out->bit_width == 0)
8520 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308521 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008522 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008523 &out->device_list, out->flags,
8524 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308525 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308526 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008527 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008528 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8529 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008530 if(adev->primary_output == NULL)
8531 adev->primary_output = out;
8532 else {
8533 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008534 ret = -EEXIST;
8535 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008536 }
8537 }
8538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008539 /* Check if this usecase is already existing */
8540 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008541 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8542 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008543 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008544 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008545 ret = -EEXIST;
8546 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008547 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008549 pthread_mutex_unlock(&adev->lock);
8550
8551 out->stream.common.get_sample_rate = out_get_sample_rate;
8552 out->stream.common.set_sample_rate = out_set_sample_rate;
8553 out->stream.common.get_buffer_size = out_get_buffer_size;
8554 out->stream.common.get_channels = out_get_channels;
8555 out->stream.common.get_format = out_get_format;
8556 out->stream.common.set_format = out_set_format;
8557 out->stream.common.standby = out_standby;
8558 out->stream.common.dump = out_dump;
8559 out->stream.common.set_parameters = out_set_parameters;
8560 out->stream.common.get_parameters = out_get_parameters;
8561 out->stream.common.add_audio_effect = out_add_audio_effect;
8562 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8563 out->stream.get_latency = out_get_latency;
8564 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008565#ifdef NO_AUDIO_OUT
8566 out->stream.write = out_write_for_no_output;
8567#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008568 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008569#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008570 out->stream.get_render_position = out_get_render_position;
8571 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008572 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008573
Haynes Mathew George16081042017-05-31 17:16:49 -07008574 if (out->realtime)
8575 out->af_period_multiplier = af_period_multiplier;
8576 else
8577 out->af_period_multiplier = 1;
8578
Andy Hunga1f48fa2019-07-01 18:14:53 -07008579 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008581 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008582 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008583 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008584
8585 config->format = out->stream.common.get_format(&out->stream.common);
8586 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8587 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308588 register_format(out->format, out->supported_formats);
8589 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8590 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008591
Aalique Grahame22e49102018-12-18 14:23:57 -08008592 out->error_log = error_log_create(
8593 ERROR_LOG_ENTRIES,
8594 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8595
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308596 /*
8597 By locking output stream before registering, we allow the callback
8598 to update stream's state only after stream's initial state is set to
8599 adev state.
8600 */
8601 lock_output_stream(out);
8602 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8603 pthread_mutex_lock(&adev->lock);
8604 out->card_status = adev->card_status;
8605 pthread_mutex_unlock(&adev->lock);
8606 pthread_mutex_unlock(&out->lock);
8607
Aalique Grahame22e49102018-12-18 14:23:57 -08008608 stream_app_type_cfg_init(&out->app_type_cfg);
8609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008610 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308611 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008612 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008613
8614 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8615 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8616 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008617 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308618 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008619 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008620 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308621 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8622 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008623 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8624 out->usecase, PCM_PLAYBACK);
8625 hdlr_stream_cfg.flags = out->flags;
8626 hdlr_stream_cfg.type = PCM_PLAYBACK;
8627 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8628 &hdlr_stream_cfg);
8629 if (ret) {
8630 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8631 out->adsp_hdlr_stream_handle = NULL;
8632 }
8633 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308634 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8635 is_direct_passthough, false);
8636 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8637 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008638 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008639 if (ret < 0) {
8640 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8641 out->ip_hdlr_handle = NULL;
8642 }
8643 }
Derek Chenf939fb72018-11-13 13:34:41 -08008644
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008645 ret = io_streams_map_insert(adev, &out->stream.common,
8646 out->handle, AUDIO_PATCH_HANDLE_NONE);
8647 if (ret != 0)
8648 goto error_open;
8649
Derek Chenf939fb72018-11-13 13:34:41 -08008650 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8651 calloc(1, sizeof(streams_output_ctxt_t));
8652 if (out_ctxt == NULL) {
8653 ALOGE("%s fail to allocate output ctxt", __func__);
8654 ret = -ENOMEM;
8655 goto error_open;
8656 }
8657 out_ctxt->output = out;
8658
8659 pthread_mutex_lock(&adev->lock);
8660 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8661 pthread_mutex_unlock(&adev->lock);
8662
Eric Laurent994a6932013-07-17 11:51:42 -07008663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008664 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008665
8666error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308667 if (out->convert_buffer)
8668 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008669 free(out);
8670 *stream_out = NULL;
8671 ALOGD("%s: exit: ret %d", __func__, ret);
8672 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008673}
8674
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308675void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008676 struct audio_stream_out *stream)
8677{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008678 struct stream_out *out = (struct stream_out *)stream;
8679 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008680 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008681
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008682 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308683
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008684 io_streams_map_remove(adev, out->handle);
8685
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308686 // must deregister from sndmonitor first to prevent races
8687 // between the callback and close_stream
8688 audio_extn_snd_mon_unregister_listener(out);
8689
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008690 /* close adsp hdrl session before standby */
8691 if (out->adsp_hdlr_stream_handle) {
8692 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8693 if (ret)
8694 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8695 out->adsp_hdlr_stream_handle = NULL;
8696 }
8697
Manish Dewangan21a850a2017-08-14 12:03:55 +05308698 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008699 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8700 out->ip_hdlr_handle = NULL;
8701 }
8702
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008703 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308704 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008705 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308706 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308707 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008708 if(ret != 0)
8709 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8710 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008711 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008712 out_standby(&stream->common);
8713
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008714 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008715 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008716 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008717 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008718 if (out->compr_config.codec != NULL)
8719 free(out->compr_config.codec);
8720 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008721
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308722 out->a2dp_compress_mute = false;
8723
Varun Balaraje49253e2017-07-06 19:48:56 +05308724 if (is_interactive_usecase(out->usecase))
8725 free_interactive_usecase(adev, out->usecase);
8726
Ashish Jain83a6cc22016-06-28 14:34:17 +05308727 if (out->convert_buffer != NULL) {
8728 free(out->convert_buffer);
8729 out->convert_buffer = NULL;
8730 }
8731
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008732 if (adev->voice_tx_output == out)
8733 adev->voice_tx_output = NULL;
8734
Aalique Grahame22e49102018-12-18 14:23:57 -08008735 error_log_destroy(out->error_log);
8736 out->error_log = NULL;
8737
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308738 if (adev->primary_output == out)
8739 adev->primary_output = NULL;
8740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008741 pthread_cond_destroy(&out->cond);
8742 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008743 pthread_mutex_destroy(&out->pre_lock);
8744 pthread_mutex_destroy(&out->latch_lock);
8745 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008746
8747 pthread_mutex_lock(&adev->lock);
8748 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8749 if (out_ctxt != NULL) {
8750 list_remove(&out_ctxt->list);
8751 free(out_ctxt);
8752 } else {
8753 ALOGW("%s, output stream already closed", __func__);
8754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008755 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008756 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008757 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008758}
8759
8760static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8761{
8762 struct audio_device *adev = (struct audio_device *)dev;
8763 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008764 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008765 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008766 int ret;
8767 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008768 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008769 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008770 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008771
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008772 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008773 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008774
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308775 if (!parms)
8776 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308777
Derek Chen6f293672019-04-01 01:40:24 -07008778 /* notify adev and input/output streams on the snd card status */
8779 adev_snd_mon_cb((void *)adev, parms);
8780
8781 list_for_each(node, &adev->active_outputs_list) {
8782 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8783 streams_output_ctxt_t,
8784 list);
8785 out_snd_mon_cb((void *)out_ctxt->output, parms);
8786 }
8787
8788 list_for_each(node, &adev->active_inputs_list) {
8789 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8790 streams_input_ctxt_t,
8791 list);
8792 in_snd_mon_cb((void *)in_ctxt->input, parms);
8793 }
8794
Zhou Songd6d71752019-05-21 18:08:51 +08008795 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308796 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8797 if (ret >= 0) {
8798 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008799 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308800 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008801 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308802 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008803 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008804 }
8805 }
8806
8807 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008808 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008809 if (!strncmp(value, "false", 5) &&
8810 audio_extn_a2dp_source_is_suspended()) {
8811 struct audio_usecase *usecase;
8812 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008813 list_for_each(node, &adev->usecase_list) {
8814 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008815 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008816 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008817 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008818 reassign_device_list(&usecase->stream.in->device_list,
8819 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008820 select_devices(adev, usecase->id);
8821 }
Zhou Songd6d71752019-05-21 18:08:51 +08008822 }
8823 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308824 }
8825
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008826 status = voice_set_parameters(adev, parms);
8827 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008828 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008829
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008830 status = platform_set_parameters(adev->platform, parms);
8831 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008832 goto done;
8833
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008834 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8835 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008836 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008837 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8838 adev->bluetooth_nrec = true;
8839 else
8840 adev->bluetooth_nrec = false;
8841 }
8842
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008843 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8844 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008845 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8846 adev->screen_off = false;
8847 else
8848 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008849 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008850 }
8851
Eric Laurent4b084132018-10-19 17:33:43 -07008852 ret = str_parms_get_int(parms, "rotation", &val);
8853 if (ret >= 0) {
8854 bool reverse_speakers = false;
8855 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8856 switch (val) {
8857 // FIXME: note that the code below assumes that the speakers are in the correct placement
8858 // relative to the user when the device is rotated 90deg from its default rotation. This
8859 // assumption is device-specific, not platform-specific like this code.
8860 case 270:
8861 reverse_speakers = true;
8862 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8863 break;
8864 case 0:
8865 case 180:
8866 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8867 break;
8868 case 90:
8869 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8870 break;
8871 default:
8872 ALOGE("%s: unexpected rotation of %d", __func__, val);
8873 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008874 }
Eric Laurent4b084132018-10-19 17:33:43 -07008875 if (status == 0) {
8876 // check and set swap
8877 // - check if orientation changed and speaker active
8878 // - set rotation and cache the rotation value
8879 adev->camera_orientation =
8880 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8881 if (!audio_extn_is_maxx_audio_enabled())
8882 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8883 }
8884 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008885
Mingming Yin514a8bc2014-07-29 15:22:21 -07008886 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8887 if (ret >= 0) {
8888 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8889 adev->bt_wb_speech_enabled = true;
8890 else
8891 adev->bt_wb_speech_enabled = false;
8892 }
8893
Zhou Song12c29502019-03-16 10:37:18 +08008894 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8895 if (ret >= 0) {
8896 val = atoi(value);
8897 adev->swb_speech_mode = val;
8898 }
8899
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008900 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8901 if (ret >= 0) {
8902 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308903 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008904 if (audio_is_output_device(val) &&
8905 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008906 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008907 platform_get_controller_stream_from_params(parms, &controller, &stream);
8908 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8909 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008910 if (ret < 0) {
8911 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308912 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008913 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008914 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308915 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008916 /*
8917 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8918 * Per AudioPolicyManager, USB device is higher priority than WFD.
8919 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8920 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8921 * starting voice call on USB
8922 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008923 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308924 if (ret >= 0)
8925 audio_extn_usb_add_device(device, atoi(value));
8926
Zhou Song6f862822017-11-06 17:27:57 +08008927 if (!audio_extn_usb_is_tunnel_supported()) {
8928 ALOGV("detected USB connect .. disable proxy");
8929 adev->allow_afe_proxy_usage = false;
8930 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008931 }
8932 }
8933
8934 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8935 if (ret >= 0) {
8936 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308937 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008938 /*
8939 * The HDMI / Displayport disconnect handling has been moved to
8940 * audio extension to ensure that its parameters are not
8941 * invalidated prior to updating sysfs of the disconnect event
8942 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8943 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308944 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008945 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308946 if (ret >= 0)
8947 audio_extn_usb_remove_device(device, atoi(value));
8948
Zhou Song6f862822017-11-06 17:27:57 +08008949 if (!audio_extn_usb_is_tunnel_supported()) {
8950 ALOGV("detected USB disconnect .. enable proxy");
8951 adev->allow_afe_proxy_usage = true;
8952 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008953 }
8954 }
8955
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008956 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008957
8958 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008959 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308960 struct audio_usecase *usecase;
8961 struct listnode *node;
8962 list_for_each(node, &adev->usecase_list) {
8963 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008964 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8965 continue;
8966
8967 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308968 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308969 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308970 ALOGD("Switching to speaker and muting the stream before select_devices");
8971 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308972 //force device switch to re configure encoder
8973 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308974 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiang280ea742020-09-08 20:28:22 +08008975 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308976 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiang280ea742020-09-08 20:28:22 +08008977 out_set_compr_volume(&usecase->stream.out->stream,
8978 usecase->stream.out->volume_l,
8979 usecase->stream.out->volume_r);
8980 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308981 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308982 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008983 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008984 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8985 if (usecase->stream.out->a2dp_compress_mute) {
8986 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8987 reassign_device_list(&usecase->stream.out->device_list,
8988 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8989 check_a2dp_restore_l(adev, usecase->stream.out, true);
8990 break;
8991 }
8992 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308993 }
8994 }
8995 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008996
8997 //handle vr audio setparam
8998 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8999 value, sizeof(value));
9000 if (ret >= 0) {
9001 ALOGI("Setting vr mode to be %s", value);
9002 if (!strncmp(value, "true", 4)) {
9003 adev->vr_audio_mode_enabled = true;
9004 ALOGI("Setting vr mode to true");
9005 } else if (!strncmp(value, "false", 5)) {
9006 adev->vr_audio_mode_enabled = false;
9007 ALOGI("Setting vr mode to false");
9008 } else {
9009 ALOGI("wrong vr mode set");
9010 }
9011 }
9012
Eric Laurent4b084132018-10-19 17:33:43 -07009013 //FIXME: to be replaced by proper video capture properties API
9014 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9015 if (ret >= 0) {
9016 int camera_facing = CAMERA_FACING_BACK;
9017 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9018 camera_facing = CAMERA_FACING_FRONT;
9019 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9020 camera_facing = CAMERA_FACING_BACK;
9021 else {
9022 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9023 goto done;
9024 }
9025 adev->camera_orientation =
9026 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9027 struct audio_usecase *usecase;
9028 struct listnode *node;
9029 list_for_each(node, &adev->usecase_list) {
9030 usecase = node_to_item(node, struct audio_usecase, list);
9031 struct stream_in *in = usecase->stream.in;
9032 if (usecase->type == PCM_CAPTURE && in != NULL &&
9033 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9034 select_devices(adev, in->usecase);
9035 }
9036 }
9037 }
9038
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309039 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009040done:
9041 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009042 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309043error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009044 ALOGV("%s: exit with code(%d)", __func__, status);
9045 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009046}
9047
9048static char* adev_get_parameters(const struct audio_hw_device *dev,
9049 const char *keys)
9050{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309051 ALOGD("%s:%s", __func__, keys);
9052
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009053 struct audio_device *adev = (struct audio_device *)dev;
9054 struct str_parms *reply = str_parms_create();
9055 struct str_parms *query = str_parms_create_str(keys);
9056 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309057 char value[256] = {0};
9058 int ret = 0;
9059
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009060 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009061 if (reply) {
9062 str_parms_destroy(reply);
9063 }
9064 if (query) {
9065 str_parms_destroy(query);
9066 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009067 ALOGE("adev_get_parameters: failed to create query or reply");
9068 return NULL;
9069 }
9070
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009071 //handle vr audio getparam
9072
9073 ret = str_parms_get_str(query,
9074 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9075 value, sizeof(value));
9076
9077 if (ret >= 0) {
9078 bool vr_audio_enabled = false;
9079 pthread_mutex_lock(&adev->lock);
9080 vr_audio_enabled = adev->vr_audio_mode_enabled;
9081 pthread_mutex_unlock(&adev->lock);
9082
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009083 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009084
9085 if (vr_audio_enabled) {
9086 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9087 "true");
9088 goto exit;
9089 } else {
9090 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9091 "false");
9092 goto exit;
9093 }
9094 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009095
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009096 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009097 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009098 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009099 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009100 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009101 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309102 pthread_mutex_unlock(&adev->lock);
9103
Naresh Tannirud7205b62014-06-20 02:54:48 +05309104exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009105 str = str_parms_to_str(reply);
9106 str_parms_destroy(query);
9107 str_parms_destroy(reply);
9108
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009109 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009110 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009111}
9112
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009113static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009114{
9115 return 0;
9116}
9117
9118static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9119{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009120 int ret;
9121 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009122
9123 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9124
Haynes Mathew George5191a852013-09-11 14:19:36 -07009125 pthread_mutex_lock(&adev->lock);
9126 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009127 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009128 pthread_mutex_unlock(&adev->lock);
9129 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009130}
9131
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009132static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9133 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009134{
9135 return -ENOSYS;
9136}
9137
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009138static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9139 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009140{
9141 return -ENOSYS;
9142}
9143
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009144static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9145 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009146{
9147 return -ENOSYS;
9148}
9149
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009150static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9151 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009152{
9153 return -ENOSYS;
9154}
9155
9156static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9157{
9158 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009159 struct listnode *node;
9160 struct audio_usecase *usecase = NULL;
9161 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009163 pthread_mutex_lock(&adev->lock);
9164 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309165 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9166 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009167 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009168 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309169 adev->current_call_output = adev->primary_output;
9170 voice_start_call(adev);
9171 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009172 (mode == AUDIO_MODE_NORMAL ||
9173 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009174 list_for_each(node, &adev->usecase_list) {
9175 usecase = node_to_item(node, struct audio_usecase, list);
9176 if (usecase->type == VOICE_CALL)
9177 break;
9178 }
9179 if (usecase &&
9180 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9181 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9182 true);
9183 if (ret != 0) {
9184 /* default service interval was successfully updated,
9185 reopen USB backend with new service interval */
9186 check_usecases_codec_backend(adev,
9187 usecase,
9188 usecase->out_snd_device);
9189 }
9190 }
9191
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009192 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009193 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009194 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009195 // restore device for other active usecases after stop call
9196 list_for_each(node, &adev->usecase_list) {
9197 usecase = node_to_item(node, struct audio_usecase, list);
9198 select_devices(adev, usecase->id);
9199 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009201 }
9202 pthread_mutex_unlock(&adev->lock);
9203 return 0;
9204}
9205
9206static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9207{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009208 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009209 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009210
9211 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009212 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009213 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009214
Derek Chend2530072014-11-24 12:39:14 -08009215 if (adev->ext_hw_plugin)
9216 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009217
9218 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009219 pthread_mutex_unlock(&adev->lock);
9220
9221 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009222}
9223
9224static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9225{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009226 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009227 return 0;
9228}
9229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009230static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231 const struct audio_config *config)
9232{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009233 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009234
Aalique Grahame22e49102018-12-18 14:23:57 -08009235 /* Don't know if USB HIFI in this context so use true to be conservative */
9236 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9237 true /*is_usb_hifi */) != 0)
9238 return 0;
9239
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009240 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9241 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009242}
9243
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009244static bool adev_input_allow_hifi_record(struct audio_device *adev,
9245 audio_devices_t devices,
9246 audio_input_flags_t flags,
9247 audio_source_t source) {
9248 const bool allowed = true;
9249
9250 if (!audio_is_usb_in_device(devices))
9251 return !allowed;
9252
9253 switch (flags) {
9254 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009255 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009256 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9257 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009258 default:
9259 return !allowed;
9260 }
9261
9262 switch (source) {
9263 case AUDIO_SOURCE_DEFAULT:
9264 case AUDIO_SOURCE_MIC:
9265 case AUDIO_SOURCE_UNPROCESSED:
9266 break;
9267 default:
9268 return !allowed;
9269 }
9270
9271 switch (adev->mode) {
9272 case 0:
9273 break;
9274 default:
9275 return !allowed;
9276 }
9277
9278 return allowed;
9279}
9280
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009281static int adev_update_voice_comm_input_stream(struct stream_in *in,
9282 struct audio_config *config)
9283{
9284 bool valid_rate = (config->sample_rate == 8000 ||
9285 config->sample_rate == 16000 ||
9286 config->sample_rate == 32000 ||
9287 config->sample_rate == 48000);
9288 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9289
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009290 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009291 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009292 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9293 in->config = default_pcm_config_voip_copp;
9294 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9295 DEFAULT_VOIP_BUF_DURATION_MS,
9296 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009297 } else {
9298 ALOGW("%s No valid input in voip, use defaults"
9299 "sample rate %u, channel mask 0x%X",
9300 __func__, config->sample_rate, in->channel_mask);
9301 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009302 in->config.rate = config->sample_rate;
9303 in->sample_rate = config->sample_rate;
9304 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009305 //XXX needed for voice_extn_compress_voip_open_input_stream
9306 in->config.rate = config->sample_rate;
9307 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309308 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009309 voice_extn_compress_voip_is_active(in->dev)) &&
9310 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9311 valid_rate && valid_ch) {
9312 voice_extn_compress_voip_open_input_stream(in);
9313 // update rate entries to match config from AF
9314 in->config.rate = config->sample_rate;
9315 in->sample_rate = config->sample_rate;
9316 } else {
9317 ALOGW("%s compress voip not active, use defaults", __func__);
9318 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009319 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009320 return 0;
9321}
9322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009323static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009324 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009325 audio_devices_t devices,
9326 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009327 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309328 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009329 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009330 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009331{
9332 struct audio_device *adev = (struct audio_device *)dev;
9333 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009334 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009335 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009336 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309337 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009338 bool is_usb_dev = audio_is_usb_in_device(devices);
9339 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9340 devices,
9341 flags,
9342 source);
Andy Hung94320602018-10-29 18:31:12 -07009343 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9344 " sample_rate %u, channel_mask %#x, format %#x",
9345 __func__, flags, is_usb_dev, may_use_hifi_record,
9346 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309347
kunleizdff872d2018-08-20 14:40:33 +08009348 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009349 is_usb_dev = false;
9350 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9351 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9352 __func__, devices);
9353 }
9354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009355 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009356
9357 if (!(is_usb_dev && may_use_hifi_record)) {
9358 if (config->sample_rate == 0)
9359 config->sample_rate = 48000;
9360 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9361 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9362 if (config->format == AUDIO_FORMAT_DEFAULT)
9363 config->format = AUDIO_FORMAT_PCM_16_BIT;
9364
9365 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9366
Aalique Grahame22e49102018-12-18 14:23:57 -08009367 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9368 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009369 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309370 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009371
Rahul Sharma99770982019-03-06 17:05:26 +05309372 pthread_mutex_lock(&adev->lock);
9373 if (in_get_stream(adev, handle) != NULL) {
9374 ALOGW("%s, input stream already opened", __func__);
9375 ret = -EEXIST;
9376 }
9377 pthread_mutex_unlock(&adev->lock);
9378 if (ret)
9379 return ret;
9380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009381 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009382
9383 if (!in) {
9384 ALOGE("failed to allocate input stream");
9385 return -ENOMEM;
9386 }
9387
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309388 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309389 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9390 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009391 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009392 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009394 in->stream.common.get_sample_rate = in_get_sample_rate;
9395 in->stream.common.set_sample_rate = in_set_sample_rate;
9396 in->stream.common.get_buffer_size = in_get_buffer_size;
9397 in->stream.common.get_channels = in_get_channels;
9398 in->stream.common.get_format = in_get_format;
9399 in->stream.common.set_format = in_set_format;
9400 in->stream.common.standby = in_standby;
9401 in->stream.common.dump = in_dump;
9402 in->stream.common.set_parameters = in_set_parameters;
9403 in->stream.common.get_parameters = in_get_parameters;
9404 in->stream.common.add_audio_effect = in_add_audio_effect;
9405 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9406 in->stream.set_gain = in_set_gain;
9407 in->stream.read = in_read;
9408 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009409 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309410 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009411 in->stream.set_microphone_direction = in_set_microphone_direction;
9412 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009413 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009414
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009415 list_init(&in->device_list);
9416 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009417 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009418 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009419 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009420 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009421 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009422 in->bit_width = 16;
9423 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009424 in->direction = MIC_DIRECTION_UNSPECIFIED;
9425 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009426 list_init(&in->aec_list);
9427 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009428 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009429
Andy Hung94320602018-10-29 18:31:12 -07009430 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009431 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9432 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9433 /* Force channel config requested to mono if incall
9434 record is being requested for only uplink/downlink */
9435 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9436 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9437 ret = -EINVAL;
9438 goto err_open;
9439 }
9440 }
9441
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009442 if (is_usb_dev && may_use_hifi_record) {
9443 /* HiFi record selects an appropriate format, channel, rate combo
9444 depending on sink capabilities*/
9445 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9446 &config->format,
9447 &in->supported_formats[0],
9448 MAX_SUPPORTED_FORMATS,
9449 &config->channel_mask,
9450 &in->supported_channel_masks[0],
9451 MAX_SUPPORTED_CHANNEL_MASKS,
9452 &config->sample_rate,
9453 &in->supported_sample_rates[0],
9454 MAX_SUPPORTED_SAMPLE_RATES);
9455 if (ret != 0) {
9456 ret = -EINVAL;
9457 goto err_open;
9458 }
9459 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009460 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309461 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309462 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9463 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9464 in->config.format = PCM_FORMAT_S32_LE;
9465 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309466 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9467 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9468 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9469 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9470 bool ret_error = false;
9471 in->bit_width = 24;
9472 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9473 from HAL is 24_packed and 8_24
9474 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9475 24_packed return error indicating supported format is 24_packed
9476 *> In case of any other source requesting 24 bit or float return error
9477 indicating format supported is 16 bit only.
9478
9479 on error flinger will retry with supported format passed
9480 */
9481 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9482 (source != AUDIO_SOURCE_CAMCORDER)) {
9483 config->format = AUDIO_FORMAT_PCM_16_BIT;
9484 if (config->sample_rate > 48000)
9485 config->sample_rate = 48000;
9486 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009487 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9488 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309489 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9490 ret_error = true;
9491 }
9492
9493 if (ret_error) {
9494 ret = -EINVAL;
9495 goto err_open;
9496 }
9497 }
9498
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009499 in->channel_mask = config->channel_mask;
9500 in->format = config->format;
9501
9502 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309503
Huicheng Liu1404ba12020-09-11 01:03:25 -04009504 /* validate bus device address */
9505 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9506 /* extract car audio stream index */
9507 in->car_audio_stream =
9508 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9509 if (in->car_audio_stream < 0) {
9510 ALOGE("%s: invalid car audio stream %x",
9511 __func__, in->car_audio_stream);
9512 ret = -EINVAL;
9513 goto err_open;
9514 }
9515 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
9516 }
9517
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309518 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9519 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9520 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9521 else {
9522 ret = -EINVAL;
9523 goto err_open;
9524 }
9525 }
9526
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009527 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309528 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9529 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009530 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9531 is_low_latency = true;
9532#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309533 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9534 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9535 else
9536 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009537#endif
9538 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009539 if (!in->realtime) {
9540 in->config = pcm_config_audio_capture;
9541 frame_size = audio_stream_in_frame_size(&in->stream);
9542 buffer_size = get_input_buffer_size(config->sample_rate,
9543 config->format,
9544 channel_count,
9545 is_low_latency);
9546 in->config.period_size = buffer_size / frame_size;
9547 in->config.rate = config->sample_rate;
9548 in->af_period_multiplier = 1;
9549 } else {
9550 // period size is left untouched for rt mode playback
9551 in->config = pcm_config_audio_capture_rt;
9552 in->af_period_multiplier = af_period_multiplier;
9553 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009554 }
9555
9556 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9557 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9558 in->realtime = 0;
9559 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9560 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009561 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009562 in->stream.start = in_start;
9563 in->stream.stop = in_stop;
9564 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9565 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009566 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009567 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009568 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9569 in->config = pcm_config_audio_capture;
9570 frame_size = audio_stream_in_frame_size(&in->stream);
9571 buffer_size = get_input_buffer_size(config->sample_rate,
9572 config->format,
9573 channel_count,
9574 false /*is_low_latency*/);
9575 in->config.period_size = buffer_size / frame_size;
9576 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009577 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009578 switch (config->format) {
9579 case AUDIO_FORMAT_PCM_32_BIT:
9580 in->bit_width = 32;
9581 break;
9582 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9583 case AUDIO_FORMAT_PCM_8_24_BIT:
9584 in->bit_width = 24;
9585 break;
9586 default:
9587 in->bit_width = 16;
9588 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009589 } else if (is_single_device_type_equal(&in->device_list,
9590 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9591 is_single_device_type_equal(&in->device_list,
9592 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009593 if (config->sample_rate == 0)
9594 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9595 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9596 config->sample_rate != 8000) {
9597 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9598 ret = -EINVAL;
9599 goto err_open;
9600 }
9601 if (config->format == AUDIO_FORMAT_DEFAULT)
9602 config->format = AUDIO_FORMAT_PCM_16_BIT;
9603 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9604 config->format = AUDIO_FORMAT_PCM_16_BIT;
9605 ret = -EINVAL;
9606 goto err_open;
9607 }
9608
9609 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009610 if (adev->ha_proxy_enable &&
9611 is_single_device_type_equal(&in->device_list,
9612 AUDIO_DEVICE_IN_TELEPHONY_RX))
9613 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009614 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009615 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009616 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309617 } else if (in->realtime) {
9618 in->config = pcm_config_audio_capture_rt;
9619 in->config.format = pcm_format_from_audio_format(config->format);
9620 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009621 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9622 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9623 (config->sample_rate == 8000 ||
9624 config->sample_rate == 16000 ||
9625 config->sample_rate == 32000 ||
9626 config->sample_rate == 48000) &&
9627 channel_count == 1) {
9628 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9629 in->config = pcm_config_audio_capture;
9630 frame_size = audio_stream_in_frame_size(&in->stream);
9631 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9632 config->sample_rate,
9633 config->format,
9634 channel_count, false /*is_low_latency*/);
9635 in->config.period_size = buffer_size / frame_size;
9636 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9637 in->config.rate = config->sample_rate;
9638 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009639 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309640 int ret_val;
9641 pthread_mutex_lock(&adev->lock);
9642 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9643 in, config, &channel_mask_updated);
9644 pthread_mutex_unlock(&adev->lock);
9645
9646 if (!ret_val) {
9647 if (channel_mask_updated == true) {
9648 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9649 __func__, config->channel_mask);
9650 ret = -EINVAL;
9651 goto err_open;
9652 }
9653 ALOGD("%s: created multi-channel session succesfully",__func__);
9654 } else if (audio_extn_compr_cap_enabled() &&
9655 audio_extn_compr_cap_format_supported(config->format) &&
9656 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9657 audio_extn_compr_cap_init(in);
9658 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309659 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309660 if (ret)
9661 goto err_open;
9662 } else {
9663 in->config = pcm_config_audio_capture;
9664 in->config.rate = config->sample_rate;
9665 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309666 in->format = config->format;
9667 frame_size = audio_stream_in_frame_size(&in->stream);
9668 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009669 config->format,
9670 channel_count,
9671 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009672 /* prevent division-by-zero */
9673 if (frame_size == 0) {
9674 ALOGE("%s: Error frame_size==0", __func__);
9675 ret = -EINVAL;
9676 goto err_open;
9677 }
9678
Revathi Uddarajud2634032017-12-07 14:42:34 +05309679 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009680 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009681
Revathi Uddarajud2634032017-12-07 14:42:34 +05309682 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9683 /* optionally use VOIP usecase depending on config(s) */
9684 ret = adev_update_voice_comm_input_stream(in, config);
9685 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009686
Revathi Uddarajud2634032017-12-07 14:42:34 +05309687 if (ret) {
9688 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9689 goto err_open;
9690 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009691 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309692
9693 /* assign concurrent capture usecase if record has to caried out from
9694 * actual hardware input source */
9695 if (audio_extn_is_concurrent_capture_enabled() &&
9696 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309697 /* Acquire lock to avoid two concurrent use cases initialized to
9698 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009699
Samyak Jainc37062f2019-04-25 18:41:06 +05309700 if (in->usecase == USECASE_AUDIO_RECORD) {
9701 pthread_mutex_lock(&adev->lock);
9702 if (!(adev->pcm_record_uc_state)) {
9703 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9704 adev->pcm_record_uc_state = 1;
9705 pthread_mutex_unlock(&adev->lock);
9706 } else {
9707 pthread_mutex_unlock(&adev->lock);
9708 /* Assign compress record use case for second record */
9709 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9710 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9711 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9712 if (audio_extn_cin_applicable_stream(in)) {
9713 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309714 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309715 if (ret)
9716 goto err_open;
9717 }
9718 }
9719 }
kunleiz28c73e72019-03-27 17:24:04 +08009720 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009721 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9722 ret = audio_extn_auto_hal_open_input_stream(in);
9723 if (ret) {
9724 ALOGE("%s: Failed to open input stream for bus device", __func__);
9725 ret = -EINVAL;
9726 goto err_open;
9727 }
9728 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009729 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309730 if (audio_extn_ssr_get_stream() != in)
9731 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009732
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009733 in->sample_rate = in->config.rate;
9734
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309735 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9736 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009737 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009738 in->sample_rate, in->bit_width,
9739 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309740 register_format(in->format, in->supported_formats);
9741 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9742 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309743
Aalique Grahame22e49102018-12-18 14:23:57 -08009744 in->error_log = error_log_create(
9745 ERROR_LOG_ENTRIES,
9746 1000000000 /* aggregate consecutive identical errors within one second */);
9747
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009748 /* This stream could be for sound trigger lab,
9749 get sound trigger pcm if present */
9750 audio_extn_sound_trigger_check_and_get_session(in);
9751
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309752 lock_input_stream(in);
9753 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9754 pthread_mutex_lock(&adev->lock);
9755 in->card_status = adev->card_status;
9756 pthread_mutex_unlock(&adev->lock);
9757 pthread_mutex_unlock(&in->lock);
9758
Aalique Grahame22e49102018-12-18 14:23:57 -08009759 stream_app_type_cfg_init(&in->app_type_cfg);
9760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009761 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009762
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009763 ret = io_streams_map_insert(adev, &in->stream.common,
9764 handle, AUDIO_PATCH_HANDLE_NONE);
9765 if (ret != 0)
9766 goto err_open;
9767
Derek Chenf939fb72018-11-13 13:34:41 -08009768 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9769 calloc(1, sizeof(streams_input_ctxt_t));
9770 if (in_ctxt == NULL) {
9771 ALOGE("%s fail to allocate input ctxt", __func__);
9772 ret = -ENOMEM;
9773 goto err_open;
9774 }
9775 in_ctxt->input = in;
9776
9777 pthread_mutex_lock(&adev->lock);
9778 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9779 pthread_mutex_unlock(&adev->lock);
9780
Eric Laurent994a6932013-07-17 11:51:42 -07009781 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009782 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009783
9784err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309785 if (in->usecase == USECASE_AUDIO_RECORD) {
9786 pthread_mutex_lock(&adev->lock);
9787 adev->pcm_record_uc_state = 0;
9788 pthread_mutex_unlock(&adev->lock);
9789 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009790 free(in);
9791 *stream_in = NULL;
9792 return ret;
9793}
9794
9795static void adev_close_input_stream(struct audio_hw_device *dev,
9796 struct audio_stream_in *stream)
9797{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009798 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009799 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009800 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309801
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309802 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009803
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009804 if (in == NULL) {
9805 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9806 return;
9807 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009808 io_streams_map_remove(adev, in->capture_handle);
9809
kunleiz70e57612018-12-28 17:50:23 +08009810 /* must deregister from sndmonitor first to prevent races
9811 * between the callback and close_stream
9812 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309813 audio_extn_snd_mon_unregister_listener(stream);
9814
kunleiz70e57612018-12-28 17:50:23 +08009815 /* Disable echo reference if there are no active input, hfp call
9816 * and sound trigger while closing input stream
9817 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009818 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009819 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009820 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9821 struct listnode out_devices;
9822 list_init(&out_devices);
9823 platform_set_echo_reference(adev, false, &out_devices);
9824 } else
kunleiz70e57612018-12-28 17:50:23 +08009825 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309826
Weiyin Jiang2995f662019-04-17 14:25:12 +08009827 error_log_destroy(in->error_log);
9828 in->error_log = NULL;
9829
Pallavid7c7a272018-01-16 11:22:55 +05309830
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009831 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309832 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009833 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309834 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009835 if (ret != 0)
9836 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9837 __func__, ret);
9838 } else
9839 in_standby(&stream->common);
9840
Weiyin Jiang280ea742020-09-08 20:28:22 +08009841 pthread_mutex_destroy(&in->lock);
9842 pthread_mutex_destroy(&in->pre_lock);
9843
Revathi Uddarajud2634032017-12-07 14:42:34 +05309844 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309845 if (in->usecase == USECASE_AUDIO_RECORD) {
9846 adev->pcm_record_uc_state = 0;
9847 }
9848
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009849 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9850 adev->enable_voicerx = false;
9851 }
9852
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009853 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009854 audio_extn_ssr_deinit();
9855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009856
Garmond Leunge2433c32017-09-28 21:51:22 -07009857 if (audio_extn_ffv_get_stream() == in) {
9858 audio_extn_ffv_stream_deinit();
9859 }
9860
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309861 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009862 audio_extn_compr_cap_format_supported(in->config.format))
9863 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309864
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309865 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309866 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009867
Mingming Yinfd7607b2016-01-22 12:48:44 -08009868 if (in->is_st_session) {
9869 ALOGV("%s: sound trigger pcm stop lab", __func__);
9870 audio_extn_sound_trigger_stop_lab(in);
9871 }
Derek Chenf939fb72018-11-13 13:34:41 -08009872 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9873 if (in_ctxt != NULL) {
9874 list_remove(&in_ctxt->list);
9875 free(in_ctxt);
9876 } else {
9877 ALOGW("%s, input stream already closed", __func__);
9878 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009879 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309880 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009881 return;
9882}
9883
Aalique Grahame22e49102018-12-18 14:23:57 -08009884/* verifies input and output devices and their capabilities.
9885 *
9886 * This verification is required when enabling extended bit-depth or
9887 * sampling rates, as not all qcom products support it.
9888 *
9889 * Suitable for calling only on initialization such as adev_open().
9890 * It fills the audio_device use_case_table[] array.
9891 *
9892 * Has a side-effect that it needs to configure audio routing / devices
9893 * in order to power up the devices and read the device parameters.
9894 * It does not acquire any hw device lock. Should restore the devices
9895 * back to "normal state" upon completion.
9896 */
9897static int adev_verify_devices(struct audio_device *adev)
9898{
9899 /* enumeration is a bit difficult because one really wants to pull
9900 * the use_case, device id, etc from the hidden pcm_device_table[].
9901 * In this case there are the following use cases and device ids.
9902 *
9903 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9904 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9905 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9906 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9907 * [USECASE_AUDIO_RECORD] = {0, 0},
9908 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9909 * [USECASE_VOICE_CALL] = {2, 2},
9910 *
9911 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9912 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9913 */
9914
9915 /* should be the usecases enabled in adev_open_input_stream() */
9916 static const int test_in_usecases[] = {
9917 USECASE_AUDIO_RECORD,
9918 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9919 };
9920 /* should be the usecases enabled in adev_open_output_stream()*/
9921 static const int test_out_usecases[] = {
9922 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9923 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9924 };
9925 static const usecase_type_t usecase_type_by_dir[] = {
9926 PCM_PLAYBACK,
9927 PCM_CAPTURE,
9928 };
9929 static const unsigned flags_by_dir[] = {
9930 PCM_OUT,
9931 PCM_IN,
9932 };
9933
9934 size_t i;
9935 unsigned dir;
9936 const unsigned card_id = adev->snd_card;
9937
9938 for (dir = 0; dir < 2; ++dir) {
9939 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9940 const unsigned flags_dir = flags_by_dir[dir];
9941 const size_t testsize =
9942 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9943 const int *testcases =
9944 dir ? test_in_usecases : test_out_usecases;
9945 const audio_devices_t audio_device =
9946 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9947
9948 for (i = 0; i < testsize; ++i) {
9949 const audio_usecase_t audio_usecase = testcases[i];
9950 int device_id;
9951 struct pcm_params **pparams;
9952 struct stream_out out;
9953 struct stream_in in;
9954 struct audio_usecase uc_info;
9955 int retval;
9956
9957 pparams = &adev->use_case_table[audio_usecase];
9958 pcm_params_free(*pparams); /* can accept null input */
9959 *pparams = NULL;
9960
9961 /* find the device ID for the use case (signed, for error) */
9962 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9963 if (device_id < 0)
9964 continue;
9965
9966 /* prepare structures for device probing */
9967 memset(&uc_info, 0, sizeof(uc_info));
9968 uc_info.id = audio_usecase;
9969 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009970 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009971 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009972 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009973 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009974 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009975 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9976 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009977 }
9978 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009979 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009980 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009981 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009982 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009983 uc_info.in_snd_device = SND_DEVICE_NONE;
9984 uc_info.out_snd_device = SND_DEVICE_NONE;
9985 list_add_tail(&adev->usecase_list, &uc_info.list);
9986
9987 /* select device - similar to start_(in/out)put_stream() */
9988 retval = select_devices(adev, audio_usecase);
9989 if (retval >= 0) {
9990 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9991#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009992 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009993 if (*pparams) {
9994 ALOGV("%s: (%s) card %d device %d", __func__,
9995 dir ? "input" : "output", card_id, device_id);
9996 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9997 } else {
9998 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9999 }
10000#endif
10001 }
10002
10003 /* deselect device - similar to stop_(in/out)put_stream() */
10004 /* 1. Get and set stream specific mixer controls */
10005 retval = disable_audio_route(adev, &uc_info);
10006 /* 2. Disable the rx device */
10007 retval = disable_snd_device(adev,
10008 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10009 list_remove(&uc_info.list);
10010 }
10011 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010012 return 0;
10013}
10014
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010015int update_patch(unsigned int num_sources,
10016 const struct audio_port_config *sources,
10017 unsigned int num_sinks,
10018 const struct audio_port_config *sinks,
10019 audio_patch_handle_t handle,
10020 struct audio_patch_info *p_info,
10021 patch_type_t patch_type, bool new_patch)
10022{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010023 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024
10025 if (p_info == NULL) {
10026 ALOGE("%s: Invalid patch pointer", __func__);
10027 return -EINVAL;
10028 }
10029
10030 if (new_patch) {
10031 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10032 if (p_info->patch == NULL) {
10033 ALOGE("%s: Could not allocate patch", __func__);
10034 return -ENOMEM;
10035 }
10036 }
10037
10038 p_info->patch->id = handle;
10039 p_info->patch->num_sources = num_sources;
10040 p_info->patch->num_sinks = num_sinks;
10041
10042 for (int i = 0; i < num_sources; i++)
10043 p_info->patch->sources[i] = sources[i];
10044 for (int i = 0; i < num_sinks; i++)
10045 p_info->patch->sinks[i] = sinks[i];
10046
10047 p_info->patch_type = patch_type;
10048 return 0;
10049}
10050
10051audio_patch_handle_t generate_patch_handle()
10052{
10053 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10054 if (++patch_handle < 0)
10055 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10056 return patch_handle;
10057}
10058
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010059int adev_create_audio_patch(struct audio_hw_device *dev,
10060 unsigned int num_sources,
10061 const struct audio_port_config *sources,
10062 unsigned int num_sinks,
10063 const struct audio_port_config *sinks,
10064 audio_patch_handle_t *handle)
10065{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010066 int ret = 0;
10067 struct audio_device *adev = (struct audio_device *)dev;
10068 struct audio_patch_info *p_info = NULL;
10069 patch_type_t patch_type = PATCH_NONE;
10070 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10071 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10072 struct audio_stream_info *s_info = NULL;
10073 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010074 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10076 bool new_patch = false;
10077 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010078
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10080 num_sources, num_sinks, *handle);
10081
10082 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10083 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10084 ALOGE("%s: Invalid patch arguments", __func__);
10085 ret = -EINVAL;
10086 goto done;
10087 }
10088
10089 if (num_sources > 1) {
10090 ALOGE("%s: Multiple sources are not supported", __func__);
10091 ret = -EINVAL;
10092 goto done;
10093 }
10094
10095 if (sources == NULL || sinks == NULL) {
10096 ALOGE("%s: Invalid sources or sinks port config", __func__);
10097 ret = -EINVAL;
10098 goto done;
10099 }
10100
10101 ALOGV("%s: source role %d, source type %d", __func__,
10102 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010103 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104
10105 // Populate source/sink information and fetch stream info
10106 switch (sources[0].type) {
10107 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10108 device_type = sources[0].ext.device.type;
10109 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010110 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010111 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10112 patch_type = PATCH_CAPTURE;
10113 io_handle = sinks[0].ext.mix.handle;
10114 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010115 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010116 __func__, device_type, io_handle);
10117 } else {
10118 // Device to device patch is not implemented.
10119 // This space will need changes if audio HAL
10120 // handles device to device patches in the future.
10121 patch_type = PATCH_DEVICE_LOOPBACK;
10122 }
10123 break;
10124 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10125 io_handle = sources[0].ext.mix.handle;
10126 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010127 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010129 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010130 }
10131 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010132 ALOGD("%s: Playback patch from mix handle %d to device %x",
10133 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010134 break;
10135 case AUDIO_PORT_TYPE_SESSION:
10136 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010137 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10138 ret = -EINVAL;
10139 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 }
10141
10142 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010143
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144 // Generate patch info and update patch
10145 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010146 *handle = generate_patch_handle();
10147 p_info = (struct audio_patch_info *)
10148 calloc(1, sizeof(struct audio_patch_info));
10149 if (p_info == NULL) {
10150 ALOGE("%s: Failed to allocate memory", __func__);
10151 pthread_mutex_unlock(&adev->lock);
10152 ret = -ENOMEM;
10153 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010154 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010155 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010156 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010157 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010158 if (p_info == NULL) {
10159 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10160 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010161 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 ret = -EINVAL;
10163 goto done;
10164 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010166 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010167 *handle, p_info, patch_type, new_patch);
10168
10169 // Fetch stream info of associated mix for playback or capture patches
10170 if (p_info->patch_type == PATCH_PLAYBACK ||
10171 p_info->patch_type == PATCH_CAPTURE) {
10172 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10173 if (s_info == NULL) {
10174 ALOGE("%s: Failed to obtain stream info", __func__);
10175 if (new_patch)
10176 free(p_info);
10177 pthread_mutex_unlock(&adev->lock);
10178 ret = -EINVAL;
10179 goto done;
10180 }
10181 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10182 s_info->patch_handle = *handle;
10183 stream = s_info->stream;
10184 }
10185 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010186
10187 // Update routing for stream
10188 if (stream != NULL) {
10189 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010190 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010191 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010192 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010193 if (ret < 0) {
10194 pthread_mutex_lock(&adev->lock);
10195 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10196 if (new_patch)
10197 free(p_info);
10198 pthread_mutex_unlock(&adev->lock);
10199 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10200 goto done;
10201 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010202 }
10203
10204 // Add new patch to patch map
10205 if (!ret && new_patch) {
10206 pthread_mutex_lock(&adev->lock);
10207 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010208 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010209 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010210 }
10211
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212done:
10213 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010214 num_sources,
10215 sources,
10216 num_sinks,
10217 sinks,
10218 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010220 num_sources,
10221 sources,
10222 num_sinks,
10223 sinks,
10224 handle);
10225 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010226}
10227
10228int adev_release_audio_patch(struct audio_hw_device *dev,
10229 audio_patch_handle_t handle)
10230{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010231 struct audio_device *adev = (struct audio_device *) dev;
10232 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010233 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010234 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010235
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010236 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10237 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10238 ret = -EINVAL;
10239 goto done;
10240 }
10241
10242 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010243 pthread_mutex_lock(&adev->lock);
10244 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010245 if (p_info == NULL) {
10246 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010247 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010248 ret = -EINVAL;
10249 goto done;
10250 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010251 struct audio_patch *patch = p_info->patch;
10252 if (patch == NULL) {
10253 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010254 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010255 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010256 goto done;
10257 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010258 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10259 switch (patch->sources[0].type) {
10260 case AUDIO_PORT_TYPE_MIX:
10261 io_handle = patch->sources[0].ext.mix.handle;
10262 break;
10263 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010264 if (p_info->patch_type == PATCH_CAPTURE)
10265 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010266 break;
10267 case AUDIO_PORT_TYPE_SESSION:
10268 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010269 pthread_mutex_unlock(&adev->lock);
10270 ret = -EINVAL;
10271 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010272 }
10273
10274 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010275 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010276 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010277 if (patch_type == PATCH_PLAYBACK ||
10278 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010279 struct audio_stream_info *s_info =
10280 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10281 if (s_info == NULL) {
10282 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10283 pthread_mutex_unlock(&adev->lock);
10284 goto done;
10285 }
10286 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10287 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010288 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010289 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010290
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010291 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010292 struct listnode devices;
10293 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010294 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010295 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010296 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010297 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010298 }
10299
10300 if (ret < 0)
10301 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10302
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010303done:
10304 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10305 audio_extn_auto_hal_release_audio_patch(dev, handle);
10306
10307 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010308 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010309}
10310
10311int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10312{
Derek Chenf13dd492018-11-13 14:53:51 -080010313 int ret = 0;
10314
10315 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10316 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10317 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010318}
10319
10320int adev_set_audio_port_config(struct audio_hw_device *dev,
10321 const struct audio_port_config *config)
10322{
Derek Chenf13dd492018-11-13 14:53:51 -080010323 int ret = 0;
10324
10325 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10326 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10327 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010328}
10329
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010330static int adev_dump(const audio_hw_device_t *device __unused,
10331 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010332{
10333 return 0;
10334}
10335
10336static int adev_close(hw_device_t *device)
10337{
Aalique Grahame22e49102018-12-18 14:23:57 -080010338 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010339 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010340
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010341 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010342 return 0;
10343
10344 pthread_mutex_lock(&adev_init_lock);
10345
10346 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010347 if (audio_extn_spkr_prot_is_enabled())
10348 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010349 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010350 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010351 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010352 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010353 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010354 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010355 audio_extn_utils_release_streams_cfg_lists(
10356 &adev->streams_output_cfg_list,
10357 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010358 if (audio_extn_qap_is_enabled())
10359 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010360 if (audio_extn_qaf_is_enabled())
10361 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010362 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010363 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010364 free(adev->snd_dev_ref_cnt);
10365 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010366 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10367 pcm_params_free(adev->use_case_table[i]);
10368 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010369 if (adev->adm_deinit)
10370 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010371 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010372 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010373 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010374 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010375 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010376 if (adev->device_cfg_params) {
10377 free(adev->device_cfg_params);
10378 adev->device_cfg_params = NULL;
10379 }
Derek Chend2530072014-11-24 12:39:14 -080010380 if(adev->ext_hw_plugin)
10381 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010382 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010383 free_map(adev->patch_map);
10384 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010385 free(device);
10386 adev = NULL;
10387 }
10388 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010389 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010390 return 0;
10391}
10392
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010393/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10394 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10395 * just that it _might_ work.
10396 */
10397static int period_size_is_plausible_for_low_latency(int period_size)
10398{
10399 switch (period_size) {
10400 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010401 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010402 case 240:
10403 case 320:
10404 case 480:
10405 return 1;
10406 default:
10407 return 0;
10408 }
10409}
10410
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010411static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10412{
10413 bool is_snd_card_status = false;
10414 bool is_ext_device_status = false;
10415 char value[32];
10416 int card = -1;
10417 card_status_t status;
10418
10419 if (cookie != adev || !parms)
10420 return;
10421
10422 if (!parse_snd_card_status(parms, &card, &status)) {
10423 is_snd_card_status = true;
10424 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10425 is_ext_device_status = true;
10426 } else {
10427 // not a valid event
10428 return;
10429 }
10430
10431 pthread_mutex_lock(&adev->lock);
10432 if (card == adev->snd_card || is_ext_device_status) {
10433 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010434 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010435 adev->card_status = status;
10436 platform_snd_card_update(adev->platform, status);
10437 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010438 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010439 if (status == CARD_STATUS_OFFLINE)
10440 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010441 } else if (is_ext_device_status) {
10442 platform_set_parameters(adev->platform, parms);
10443 }
10444 }
10445 pthread_mutex_unlock(&adev->lock);
10446 return;
10447}
10448
Weiyin Jiang280ea742020-09-08 20:28:22 +080010449/* adev lock held */
10450int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010451{
10452 struct audio_usecase *uc_info;
10453 float left_p;
10454 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010455 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010456
10457 uc_info = get_usecase_from_list(adev, out->usecase);
10458 if (uc_info == NULL) {
10459 ALOGE("%s: Could not find the usecase (%d) in the list",
10460 __func__, out->usecase);
10461 return -EINVAL;
10462 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010463 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010464
10465 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10466 out->usecase, use_case_table[out->usecase]);
10467
10468 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010469 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010470 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010471 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010472 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010473 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10474 select_devices(adev, uc_info->id);
Zhou Songd01e7a22020-09-23 22:49:01 +080010475 if (is_offload_usecase(out->usecase) &&
Weiyin Jiang280ea742020-09-08 20:28:22 +080010476 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10477 if (out->a2dp_compress_mute) {
10478 out->a2dp_compress_mute = false;
10479 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10480 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010482 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010483 out->muted = false;
10484 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010485 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010486 pthread_mutex_lock(&out->latch_lock);
Zhou Songd01e7a22020-09-23 22:49:01 +080010487 if (is_offload_usecase(out->usecase)) {
Zhou Songc576a452019-09-09 14:17:40 +080010488 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010489 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010490 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010491 assign_devices(&devices, &out->device_list);
10492 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010493 left_p = out->volume_l;
10494 right_p = out->volume_r;
10495 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10496 compress_pause(out->compr);
10497 out_set_compr_volume(&out->stream, (float)0, (float)0);
10498 out->a2dp_compress_mute = true;
10499 select_devices(adev, out->usecase);
10500 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10501 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010502 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010503 out->volume_l = left_p;
10504 out->volume_r = right_p;
10505 }
Zhou Songc576a452019-09-09 14:17:40 +080010506 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010507 // mute for non offloaded streams
10508 if (audio_extn_a2dp_source_is_suspended()) {
10509 out->muted = true;
10510 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010511 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010512 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010513 }
10514 ALOGV("%s: exit", __func__);
10515 return 0;
10516}
10517
Haynes Mathew George01156f92018-04-13 15:29:54 -070010518void adev_on_battery_status_changed(bool charging)
10519{
10520 pthread_mutex_lock(&adev->lock);
10521 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10522 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010523 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010524 pthread_mutex_unlock(&adev->lock);
10525}
10526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010527static int adev_open(const hw_module_t *module, const char *name,
10528 hw_device_t **device)
10529{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010530 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010531 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010532 char mixer_ctl_name[128] = {0};
10533 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010534
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010535 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010536 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10537
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010538 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010539 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010540 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010541 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010542 ALOGD("%s: returning existing instance of adev", __func__);
10543 ALOGD("%s: exit", __func__);
10544 pthread_mutex_unlock(&adev_init_lock);
10545 return 0;
10546 }
10547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010548 adev = calloc(1, sizeof(struct audio_device));
10549
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010550 if (!adev) {
10551 pthread_mutex_unlock(&adev_init_lock);
10552 return -ENOMEM;
10553 }
10554
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010555 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10556
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010557 // register audio ext hidl at the earliest
10558 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010559#ifdef DYNAMIC_LOG_ENABLED
10560 register_for_dynamic_logging("hal");
10561#endif
10562
Derek Chenf939fb72018-11-13 13:34:41 -080010563 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010564 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010565 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10566 maj_version = atoi(value);
10567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010568 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010569 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010570 adev->device.common.module = (struct hw_module_t *)module;
10571 adev->device.common.close = adev_close;
10572
10573 adev->device.init_check = adev_init_check;
10574 adev->device.set_voice_volume = adev_set_voice_volume;
10575 adev->device.set_master_volume = adev_set_master_volume;
10576 adev->device.get_master_volume = adev_get_master_volume;
10577 adev->device.set_master_mute = adev_set_master_mute;
10578 adev->device.get_master_mute = adev_get_master_mute;
10579 adev->device.set_mode = adev_set_mode;
10580 adev->device.set_mic_mute = adev_set_mic_mute;
10581 adev->device.get_mic_mute = adev_get_mic_mute;
10582 adev->device.set_parameters = adev_set_parameters;
10583 adev->device.get_parameters = adev_get_parameters;
10584 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10585 adev->device.open_output_stream = adev_open_output_stream;
10586 adev->device.close_output_stream = adev_close_output_stream;
10587 adev->device.open_input_stream = adev_open_input_stream;
10588 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010589 adev->device.create_audio_patch = adev_create_audio_patch;
10590 adev->device.release_audio_patch = adev_release_audio_patch;
10591 adev->device.get_audio_port = adev_get_audio_port;
10592 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010593 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010594 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010595
10596 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010597 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010598 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010599 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010600 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010601 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010602 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010603 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010604 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010605 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010606 /* Init audio and voice feature */
10607 audio_extn_feature_init();
10608 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010609 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010610 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010611 list_init(&adev->active_inputs_list);
10612 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010613 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010614 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10615 audio_extn_utils_hash_eq);
10616 if (!adev->io_streams_map) {
10617 ALOGE("%s: Could not create io streams map", __func__);
10618 ret = -ENOMEM;
10619 goto adev_open_err;
10620 }
10621 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10622 audio_extn_utils_hash_eq);
10623 if (!adev->patch_map) {
10624 ALOGE("%s: Could not create audio patch map", __func__);
10625 ret = -ENOMEM;
10626 goto adev_open_err;
10627 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010628 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010629 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010630 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010631 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010632 adev->perf_lock_opts[0] = 0x101;
10633 adev->perf_lock_opts[1] = 0x20E;
10634 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010635 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010636 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010637 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010638 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010639 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010640
Zhou Song68ebc352019-12-05 17:11:15 +080010641 audio_extn_perf_lock_init();
10642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010643 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010644 adev->platform = platform_init(adev);
10645 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010646 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010647 ret = -EINVAL;
10648 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010649 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010650
Aalique Grahame22e49102018-12-18 14:23:57 -080010651 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010652 if (audio_extn_qap_is_enabled()) {
10653 ret = audio_extn_qap_init(adev);
10654 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010655 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010656 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010657 }
10658 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10659 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10660 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010661
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010662 if (audio_extn_qaf_is_enabled()) {
10663 ret = audio_extn_qaf_init(adev);
10664 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010665 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010666 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010667 }
10668
10669 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10670 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10671 }
10672
Derek Chenae7b0342019-02-08 15:17:04 -080010673 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010674 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10675
Eric Laurentc4aef752013-09-12 17:45:53 -070010676 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10677 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10678 if (adev->visualizer_lib == NULL) {
10679 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10680 } else {
10681 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10682 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010683 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010684 "visualizer_hal_start_output");
10685 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010686 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010687 "visualizer_hal_stop_output");
10688 }
10689 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010690 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010691 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010692 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010693 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010694 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010695 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010696
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010697 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10698 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10699 if (adev->offload_effects_lib == NULL) {
10700 ALOGE("%s: DLOPEN failed for %s", __func__,
10701 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10702 } else {
10703 ALOGV("%s: DLOPEN successful for %s", __func__,
10704 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10705 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010706 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010707 "offload_effects_bundle_hal_start_output");
10708 adev->offload_effects_stop_output =
10709 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10710 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010711 adev->offload_effects_set_hpx_state =
10712 (int (*)(bool))dlsym(adev->offload_effects_lib,
10713 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010714 adev->offload_effects_get_parameters =
10715 (void (*)(struct str_parms *, struct str_parms *))
10716 dlsym(adev->offload_effects_lib,
10717 "offload_effects_bundle_get_parameters");
10718 adev->offload_effects_set_parameters =
10719 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10720 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010721 }
10722 }
10723
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010724 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10725 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10726 if (adev->adm_lib == NULL) {
10727 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10728 } else {
10729 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10730 adev->adm_init = (adm_init_t)
10731 dlsym(adev->adm_lib, "adm_init");
10732 adev->adm_deinit = (adm_deinit_t)
10733 dlsym(adev->adm_lib, "adm_deinit");
10734 adev->adm_register_input_stream = (adm_register_input_stream_t)
10735 dlsym(adev->adm_lib, "adm_register_input_stream");
10736 adev->adm_register_output_stream = (adm_register_output_stream_t)
10737 dlsym(adev->adm_lib, "adm_register_output_stream");
10738 adev->adm_deregister_stream = (adm_deregister_stream_t)
10739 dlsym(adev->adm_lib, "adm_deregister_stream");
10740 adev->adm_request_focus = (adm_request_focus_t)
10741 dlsym(adev->adm_lib, "adm_request_focus");
10742 adev->adm_abandon_focus = (adm_abandon_focus_t)
10743 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010744 adev->adm_set_config = (adm_set_config_t)
10745 dlsym(adev->adm_lib, "adm_set_config");
10746 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10747 dlsym(adev->adm_lib, "adm_request_focus_v2");
10748 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10749 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10750 adev->adm_on_routing_change = (adm_on_routing_change_t)
10751 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010752 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10753 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010754 }
10755 }
10756
Aalique Grahame22e49102018-12-18 14:23:57 -080010757 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010758 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010759 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010760 //initialize this to false for now,
10761 //this will be set to true through set param
10762 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010763
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010764 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010765 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010766
10767 if (k_enable_extended_precision)
10768 adev_verify_devices(adev);
10769
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010770 adev->dsp_bit_width_enforce_mode =
10771 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010772
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010773 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10774 &adev->streams_output_cfg_list,
10775 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010776
Kiran Kandi910e1862013-10-29 13:29:42 -070010777 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010778
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010779 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010780 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010781 trial = atoi(value);
10782 if (period_size_is_plausible_for_low_latency(trial)) {
10783 pcm_config_low_latency.period_size = trial;
10784 pcm_config_low_latency.start_threshold = trial / 4;
10785 pcm_config_low_latency.avail_min = trial / 4;
10786 configured_low_latency_capture_period_size = trial;
10787 }
10788 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010789 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10790 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010791 trial = atoi(value);
10792 if (period_size_is_plausible_for_low_latency(trial)) {
10793 configured_low_latency_capture_period_size = trial;
10794 }
10795 }
10796
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010797 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10798
Eric Laurent4b084132018-10-19 17:33:43 -070010799 adev->camera_orientation = CAMERA_DEFAULT;
10800
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010801 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010802 af_period_multiplier = atoi(value);
10803 if (af_period_multiplier < 0)
10804 af_period_multiplier = 2;
10805 else if (af_period_multiplier > 4)
10806 af_period_multiplier = 4;
10807
10808 ALOGV("new period_multiplier = %d", af_period_multiplier);
10809 }
10810
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010811 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010812
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010813 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010814 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010815 pthread_mutex_unlock(&adev_init_lock);
10816
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010817 if (adev->adm_init)
10818 adev->adm_data = adev->adm_init();
10819
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010820 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010821 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010822
10823 audio_extn_snd_mon_init();
10824 pthread_mutex_lock(&adev->lock);
10825 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10826 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010827 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10828 /*
10829 * if the battery state callback happens before charging can be queried,
10830 * it will be guarded with the adev->lock held in the cb function and so
10831 * the callback value will reflect the latest state
10832 */
10833 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010834 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010835 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010836 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010837 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010838 /* Allocate memory for Device config params */
10839 adev->device_cfg_params = (struct audio_device_config_param*)
10840 calloc(platform_get_max_codec_backend(),
10841 sizeof(struct audio_device_config_param));
10842 if (adev->device_cfg_params == NULL)
10843 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010844
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010845 /*
10846 * Check if new PSPD matrix mixer control is supported. If not
10847 * supported, then set flag so that old mixer ctrl is sent while
10848 * sending pspd coefficients on older kernel version. Query mixer
10849 * control for default pcm id and channel value one.
10850 */
10851 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10852 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10853
10854 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10855 if (!ctl) {
10856 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10857 __func__, mixer_ctl_name);
10858 adev->use_old_pspd_mix_ctrl = true;
10859 }
10860
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010861 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010862 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010863
10864adev_open_err:
10865 free_map(adev->patch_map);
10866 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010867 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010868 pthread_mutex_destroy(&adev->lock);
10869 free(adev);
10870 adev = NULL;
10871 *device = NULL;
10872 pthread_mutex_unlock(&adev_init_lock);
10873 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010874}
10875
10876static struct hw_module_methods_t hal_module_methods = {
10877 .open = adev_open,
10878};
10879
10880struct audio_module HAL_MODULE_INFO_SYM = {
10881 .common = {
10882 .tag = HARDWARE_MODULE_TAG,
10883 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10884 .hal_api_version = HARDWARE_HAL_API_VERSION,
10885 .id = AUDIO_HARDWARE_MODULE_ID,
10886 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010887 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010888 .methods = &hal_module_methods,
10889 },
10890};