blob: ef6bc40aba5febae11c282eaf32418a7a9f31578 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Ramu Gottipatifa5be522021-12-28 19:18:21 +05302 * Copyright (c) 2013-2022, 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
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Dechen Chai22768452021-07-30 09:29:16 +0530151#ifdef LINUX_ENABLED
152static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
153{
154 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
155}
156#endif
157
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700158static unsigned int configured_low_latency_capture_period_size =
159 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
160
Haynes Mathew George16081042017-05-31 17:16:49 -0700161#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
162#define MMAP_PERIOD_COUNT_MIN 32
163#define MMAP_PERIOD_COUNT_MAX 512
164#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
165
Aalique Grahame22e49102018-12-18 14:23:57 -0800166/* This constant enables extended precision handling.
167 * TODO The flag is off until more testing is done.
168 */
169static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700170extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_deep_buffer = {
173 .channels = 2,
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
179 .stop_threshold = INT_MAX,
180 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
181};
182
183struct pcm_config pcm_config_low_latency = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
187 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190 .stop_threshold = INT_MAX,
191 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
192};
193
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800194struct pcm_config pcm_config_haptics_audio = {
195 .channels = 1,
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
197 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
199 .format = PCM_FORMAT_S16_LE,
200 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201 .stop_threshold = INT_MAX,
202 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
203};
204
205struct pcm_config pcm_config_haptics = {
206 .channels = 1,
207 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
208 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
209 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
212 .stop_threshold = INT_MAX,
213 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
214};
215
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700216static int af_period_multiplier = 4;
217struct pcm_config pcm_config_rt = {
218 .channels = 2,
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
220 .period_size = ULL_PERIOD_SIZE, //1 ms
221 .period_count = 512, //=> buffer size is 512ms
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
224 .stop_threshold = INT_MAX,
225 .silence_threshold = 0,
226 .silence_size = 0,
227 .avail_min = ULL_PERIOD_SIZE, //1 ms
228};
229
Eric Laurentb23d5282013-05-14 15:27:20 -0700230struct pcm_config pcm_config_hdmi_multi = {
231 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
232 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
233 .period_size = HDMI_MULTI_PERIOD_SIZE,
234 .period_count = HDMI_MULTI_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = 0,
237 .stop_threshold = INT_MAX,
238 .avail_min = 0,
239};
240
Haynes Mathew George16081042017-05-31 17:16:49 -0700241struct pcm_config pcm_config_mmap_playback = {
242 .channels = 2,
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
244 .period_size = MMAP_PERIOD_SIZE,
245 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = MMAP_PERIOD_SIZE*8,
248 .stop_threshold = INT32_MAX,
249 .silence_threshold = 0,
250 .silence_size = 0,
251 .avail_min = MMAP_PERIOD_SIZE, //1 ms
252};
253
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700254struct pcm_config pcm_config_hifi = {
255 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
256 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
257 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
258 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
259 .format = PCM_FORMAT_S24_3LE,
260 .start_threshold = 0,
261 .stop_threshold = INT_MAX,
262 .avail_min = 0,
263};
264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265struct pcm_config pcm_config_audio_capture = {
266 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700267 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
268 .format = PCM_FORMAT_S16_LE,
269};
270
Haynes Mathew George16081042017-05-31 17:16:49 -0700271struct pcm_config pcm_config_mmap_capture = {
272 .channels = 2,
273 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
274 .period_size = MMAP_PERIOD_SIZE,
275 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
276 .format = PCM_FORMAT_S16_LE,
277 .start_threshold = 0,
278 .stop_threshold = INT_MAX,
279 .silence_threshold = 0,
280 .silence_size = 0,
281 .avail_min = MMAP_PERIOD_SIZE, //1 ms
282};
283
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700284#define AFE_PROXY_CHANNEL_COUNT 2
285#define AFE_PROXY_SAMPLING_RATE 48000
286
287#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
288#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
289
290struct pcm_config pcm_config_afe_proxy_playback = {
291 .channels = AFE_PROXY_CHANNEL_COUNT,
292 .rate = AFE_PROXY_SAMPLING_RATE,
293 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
294 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
297 .stop_threshold = INT_MAX,
298 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
299};
300
301#define AFE_PROXY_RECORD_PERIOD_SIZE 768
302#define AFE_PROXY_RECORD_PERIOD_COUNT 4
303
Aalique Grahame22e49102018-12-18 14:23:57 -0800304struct pcm_config pcm_config_audio_capture_rt = {
305 .channels = 2,
306 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
307 .period_size = ULL_PERIOD_SIZE,
308 .period_count = 512,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = 0,
311 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
312 .silence_threshold = 0,
313 .silence_size = 0,
314 .avail_min = ULL_PERIOD_SIZE, //1 ms
315};
316
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530317struct pcm_config pcm_config_audio_capture_rt_48KHz = {
318 .channels = 2,
319 .rate = 48000,
320 .period_size = 48,
321 .period_count = 512,
322 .format = PCM_FORMAT_S16_LE,
323 .start_threshold = 0,
324 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
325 .silence_threshold = 0,
326 .silence_size = 0,
327 .avail_min = 48, //1 ms
328};
329struct pcm_config pcm_config_audio_capture_rt_32KHz = {
330 .channels = 2,
331 .rate = 32000,
332 .period_size = 32,
333 .period_count = 512,
334 .format = PCM_FORMAT_S16_LE,
335 .start_threshold = 0,
336 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
337 .silence_threshold = 0,
338 .silence_size = 0,
339 .avail_min = 32, //1 ms
340};
341struct pcm_config pcm_config_audio_capture_rt_24KHz = {
342 .channels = 2,
343 .rate = 24000,
344 .period_size = 24,
345 .period_count = 512,
346 .format = PCM_FORMAT_S16_LE,
347 .start_threshold = 0,
348 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
349 .silence_threshold = 0,
350 .silence_size = 0,
351 .avail_min = 24, //1 ms
352};
353struct pcm_config pcm_config_audio_capture_rt_16KHz = {
354 .channels = 2,
355 .rate = 16000,
356 .period_size = 16,
357 .period_count = 512,
358 .format = PCM_FORMAT_S16_LE,
359 .start_threshold = 0,
360 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
361 .silence_threshold = 0,
362 .silence_size = 0,
363 .avail_min = 16, //1 ms
364};
365struct pcm_config pcm_config_audio_capture_rt_8KHz = {
366 .channels = 2,
367 .rate = 8000,
368 .period_size = 8,
369 .period_count = 512,
370 .format = PCM_FORMAT_S16_LE,
371 .start_threshold = 0,
372 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
373 .silence_threshold = 0,
374 .silence_size = 0,
375 .avail_min = 8, //1 ms
376};
377
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700378struct pcm_config pcm_config_afe_proxy_record = {
379 .channels = AFE_PROXY_CHANNEL_COUNT,
380 .rate = AFE_PROXY_SAMPLING_RATE,
381 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
382 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
383 .format = PCM_FORMAT_S16_LE,
384 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
385 .stop_threshold = INT_MAX,
386 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
387};
388
Ashish Jainf1eaa582016-05-23 20:54:24 +0530389#define AUDIO_MAX_PCM_FORMATS 7
390
391const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
392 [AUDIO_FORMAT_DEFAULT] = 0,
393 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
394 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
395 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
396 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
397 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
398 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
399};
400
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800401const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700402 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
403 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800404 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800405 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700406 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
407 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700408 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700409 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700410 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
411 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
412 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
413 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
414 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
415 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
416 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
417 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700418 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
419 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700420 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800421 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700422
Eric Laurentb23d5282013-05-14 15:27:20 -0700423 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530424 [USECASE_AUDIO_RECORD2] = "audio-record2",
425 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700426 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530427 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
428 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
429 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530430 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
431 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700432 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700433 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700434 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700436
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800437 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800438 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400439 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
440 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700441
Derek Chenf7092792017-05-23 12:23:53 -0400442 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700443 [USECASE_VOICE2_CALL] = "voice2-call",
444 [USECASE_VOLTE_CALL] = "volte-call",
445 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800446 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800447 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
448 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800449 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700450 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
451 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
452 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800453 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
454 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
455 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
456
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700457 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
458 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700459 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
460 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700461
462 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
463 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800464 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530465 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700466
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530467 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530468 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
469 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700470
471 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
472 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530473 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530474 /* For Interactive Audio Streams */
475 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
476 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
477 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
478 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
479 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
480 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
481 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
482 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700483
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800484 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
485
Derek Chenf6318be2017-06-12 17:16:24 -0400486 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
487
488 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
489 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
490 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
491 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800492 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700493 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530494 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500495 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400496
497 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
498 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
499 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800500 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500501 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700502};
503
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700504static const audio_usecase_t offload_usecases[] = {
505 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700506 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
507 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
508 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
509 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
510 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
511 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
512 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
513 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700514};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800515
Varun Balaraje49253e2017-07-06 19:48:56 +0530516static const audio_usecase_t interactive_usecases[] = {
517 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
518 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
519 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
520 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
521 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
522 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
523 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
524 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
525};
526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527#define STRING_TO_ENUM(string) { #string, string }
528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529struct string_to_enum {
530 const char *name;
531 uint32_t value;
532};
533
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700534static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800536 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
537 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
538 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700539 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800540 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
541 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700543 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
544 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
545 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
546 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
547 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
548 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
549 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
550 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
551 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
552 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
553 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554};
555
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700556static const struct string_to_enum formats_name_to_enum_table[] = {
557 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
558 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
559 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700560 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
561 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
562 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700563 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800564 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
565 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700566 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800567};
568
569//list of all supported sample rates by HDMI specification.
570static const int out_hdmi_sample_rates[] = {
571 32000, 44100, 48000, 88200, 96000, 176400, 192000,
572};
573
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700574static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800575 STRING_TO_ENUM(32000),
576 STRING_TO_ENUM(44100),
577 STRING_TO_ENUM(48000),
578 STRING_TO_ENUM(88200),
579 STRING_TO_ENUM(96000),
580 STRING_TO_ENUM(176400),
581 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800582 STRING_TO_ENUM(352800),
583 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700584};
585
Carter Hsu2e429db2019-05-14 18:50:52 +0800586struct in_effect_list {
587 struct listnode list;
588 effect_handle_t handle;
589};
590
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530591static const audio_usecase_t record_usecases[] = {
592 USECASE_AUDIO_RECORD,
593 USECASE_AUDIO_RECORD2,
594 USECASE_AUDIO_RECORD3,
595};
596
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700597static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700598static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700599static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700600//cache last MBDRC cal step level
601static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700602
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530603static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700604static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800605static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530606static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530607#ifdef SOFT_VOLUME
608static int out_set_soft_volume_params(struct audio_stream_out *stream);
609#endif
Derek Chen6f293672019-04-01 01:40:24 -0700610static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
611static void in_snd_mon_cb(void * stream, struct str_parms * parms);
612static void out_snd_mon_cb(void * stream, struct str_parms * parms);
613
Zhou Song331c8e52019-08-26 14:16:12 +0800614static int configure_btsco_sample_rate(snd_device_t snd_device);
615
Vatsal Buchac09ae062018-11-14 13:25:08 +0530616#ifdef AUDIO_FEATURE_ENABLED_GCOV
617extern void __gcov_flush();
618static void enable_gcov()
619{
620 __gcov_flush();
621}
622#else
623static void enable_gcov()
624{
625}
626#endif
627
justinweng20fb6d82019-02-21 18:49:00 -0700628static int in_set_microphone_direction(const struct audio_stream_in *stream,
629 audio_microphone_direction_t dir);
630static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
631
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530632static bool is_pcm_record_usecase(audio_usecase_t uc_id)
633{
634 unsigned int record_uc_index;
635 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
636
637 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
638 if (uc_id == record_usecases[record_uc_index])
639 return true;
640 }
641 return false;
642}
643
644static audio_usecase_t get_record_usecase(struct audio_device *adev)
645{
646 audio_usecase_t ret_uc = USECASE_INVALID;
647 unsigned int record_uc_index;
648 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
649
650 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
651 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
652 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
653 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
654 ret_uc = record_usecases[record_uc_index];
655 break;
656 }
657 }
658
659 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
660 return ret_uc;
661}
662
663static void free_record_usecase(struct audio_device *adev,
664 audio_usecase_t uc_id)
665{
666 unsigned int record_uc_index;
667 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
668
669 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
670 if (record_usecases[record_uc_index] == uc_id) {
671 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
672 break;
673 }
674 }
675 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
676}
677
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700678static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
679 int flags __unused)
680{
681 int dir = 0;
682 switch (uc_id) {
683 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530684 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700685 dir = 1;
686 case USECASE_AUDIO_PLAYBACK_ULL:
687 break;
688 default:
689 return false;
690 }
691
692 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
693 PCM_PLAYBACK : PCM_CAPTURE);
694 if (adev->adm_is_noirq_avail)
695 return adev->adm_is_noirq_avail(adev->adm_data,
696 adev->snd_card, dev_id, dir);
697 return false;
698}
699
700static void register_out_stream(struct stream_out *out)
701{
702 struct audio_device *adev = out->dev;
703 if (is_offload_usecase(out->usecase) ||
704 !adev->adm_register_output_stream)
705 return;
706
707 // register stream first for backward compatibility
708 adev->adm_register_output_stream(adev->adm_data,
709 out->handle,
710 out->flags);
711
712 if (!adev->adm_set_config)
713 return;
714
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530715 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
716 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700717 out->handle,
718 out->pcm, &out->config);
719}
720
721static void register_in_stream(struct stream_in *in)
722{
723 struct audio_device *adev = in->dev;
724 if (!adev->adm_register_input_stream)
725 return;
726
727 adev->adm_register_input_stream(adev->adm_data,
728 in->capture_handle,
729 in->flags);
730
731 if (!adev->adm_set_config)
732 return;
733
734 if (in->realtime)
735 adev->adm_set_config(adev->adm_data,
736 in->capture_handle,
737 in->pcm,
738 &in->config);
739}
740
741static void request_out_focus(struct stream_out *out, long ns)
742{
743 struct audio_device *adev = out->dev;
744
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700745 if (adev->adm_request_focus_v2)
746 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
747 else if (adev->adm_request_focus)
748 adev->adm_request_focus(adev->adm_data, out->handle);
749}
750
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700751static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700752{
753 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700754 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700755
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700756 if (adev->adm_request_focus_v2_1)
757 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
758 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700759 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
760 else if (adev->adm_request_focus)
761 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700762
763 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700764}
765
766static void release_out_focus(struct stream_out *out)
767{
768 struct audio_device *adev = out->dev;
769
770 if (adev->adm_abandon_focus)
771 adev->adm_abandon_focus(adev->adm_data, out->handle);
772}
773
774static void release_in_focus(struct stream_in *in)
775{
776 struct audio_device *adev = in->dev;
777 if (adev->adm_abandon_focus)
778 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
779}
780
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530781static int parse_snd_card_status(struct str_parms *parms, int *card,
782 card_status_t *status)
783{
784 char value[32]={0};
785 char state[32]={0};
786
787 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
788 if (ret < 0)
789 return -1;
790
791 // sscanf should be okay as value is of max length 32.
792 // same as sizeof state.
793 if (sscanf(value, "%d,%s", card, state) < 2)
794 return -1;
795
796 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
797 CARD_STATUS_OFFLINE;
798 return 0;
799}
800
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700801static inline void adjust_frames_for_device_delay(struct stream_out *out,
802 uint32_t *dsp_frames) {
803 // Adjustment accounts for A2dp encoder latency with offload usecases
804 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800805 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700806 unsigned long offset =
807 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
808 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
809 }
810}
811
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700812static inline bool free_entry(void *key __unused,
813 void *value, void *context __unused)
814{
815 free(value);
816 return true;
817}
818
819static inline void free_map(Hashmap *map)
820{
821 if (map) {
822 hashmapForEach(map, free_entry, (void *) NULL);
823 hashmapFree(map);
824 }
825}
826
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800827static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700828 audio_patch_handle_t patch_handle)
829{
830 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
831 return;
832
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700833 struct audio_patch_info *p_info =
834 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
835 if (p_info) {
836 ALOGV("%s: Remove patch %d", __func__, patch_handle);
837 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
838 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700839 free(p_info);
840 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700841}
842
843static inline int io_streams_map_insert(struct audio_device *adev,
844 struct audio_stream *stream,
845 audio_io_handle_t handle,
846 audio_patch_handle_t patch_handle)
847{
848 struct audio_stream_info *s_info =
849 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
850
851 if (s_info == NULL) {
852 ALOGE("%s: Could not allocate stream info", __func__);
853 return -ENOMEM;
854 }
855 s_info->stream = stream;
856 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700857
858 pthread_mutex_lock(&adev->lock);
859 struct audio_stream_info *stream_info =
860 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700861 if (stream_info != NULL)
862 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800863 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700864 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700865 return 0;
866}
867
868static inline void io_streams_map_remove(struct audio_device *adev,
869 audio_io_handle_t handle)
870{
871 pthread_mutex_lock(&adev->lock);
872 struct audio_stream_info *s_info =
873 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700874 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800875 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700876 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800877 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700878 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800879done:
880 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700881 return;
882}
883
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800884static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700885 audio_patch_handle_t handle)
886{
887 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700888 p_info = (struct audio_patch_info *)
889 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700890 return p_info;
891}
892
vivek mehtaa76401a2015-04-24 14:12:15 -0700893__attribute__ ((visibility ("default")))
894bool audio_hw_send_gain_dep_calibration(int level) {
895 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700896 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700897
898 pthread_mutex_lock(&adev_init_lock);
899
900 if (adev != NULL && adev->platform != NULL) {
901 pthread_mutex_lock(&adev->lock);
902 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700903
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530904 // cache level info for any of the use case which
905 // was not started.
906 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700907
vivek mehtaa76401a2015-04-24 14:12:15 -0700908 pthread_mutex_unlock(&adev->lock);
909 } else {
910 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
911 }
912
913 pthread_mutex_unlock(&adev_init_lock);
914
915 return ret_val;
916}
917
Ashish Jain5106d362016-05-11 19:23:33 +0530918static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
919{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800920 bool gapless_enabled = false;
921 const char *mixer_ctl_name = "Compress Gapless Playback";
922 struct mixer_ctl *ctl;
923
924 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700925 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530926
927 /*Disable gapless if its AV playback*/
928 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800929
930 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
931 if (!ctl) {
932 ALOGE("%s: Could not get ctl for mixer cmd - %s",
933 __func__, mixer_ctl_name);
934 return -EINVAL;
935 }
936
937 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
938 ALOGE("%s: Could not set gapless mode %d",
939 __func__, gapless_enabled);
940 return -EINVAL;
941 }
942 return 0;
943}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700944
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700945__attribute__ ((visibility ("default")))
946int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
947 int table_size) {
948 int ret_val = 0;
949 ALOGV("%s: enter ... ", __func__);
950
951 pthread_mutex_lock(&adev_init_lock);
952 if (adev == NULL) {
953 ALOGW("%s: adev is NULL .... ", __func__);
954 goto done;
955 }
956
957 pthread_mutex_lock(&adev->lock);
958 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
959 pthread_mutex_unlock(&adev->lock);
960done:
961 pthread_mutex_unlock(&adev_init_lock);
962 ALOGV("%s: exit ... ", __func__);
963 return ret_val;
964}
965
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800966bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800967{
968 bool ret = false;
969 ALOGV("%s: enter ...", __func__);
970
971 pthread_mutex_lock(&adev_init_lock);
972
973 if (adev != NULL && adev->platform != NULL) {
974 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800975 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800976 pthread_mutex_unlock(&adev->lock);
977 }
978
979 pthread_mutex_unlock(&adev_init_lock);
980
981 ALOGV("%s: exit with ret %d", __func__, ret);
982 return ret;
983}
Aalique Grahame22e49102018-12-18 14:23:57 -0800984
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700985static bool is_supported_format(audio_format_t format)
986{
Eric Laurent86e17132013-09-12 17:49:30 -0700987 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530988 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530989 format == AUDIO_FORMAT_AAC_LC ||
990 format == AUDIO_FORMAT_AAC_HE_V1 ||
991 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530992 format == AUDIO_FORMAT_AAC_ADTS_LC ||
993 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
994 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530995 format == AUDIO_FORMAT_AAC_LATM_LC ||
996 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
997 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530998 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
999 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301000 format == AUDIO_FORMAT_PCM_FLOAT ||
1001 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001002 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301003 format == AUDIO_FORMAT_AC3 ||
1004 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001005 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301006 format == AUDIO_FORMAT_DTS ||
1007 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001008 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301009 format == AUDIO_FORMAT_ALAC ||
1010 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301011 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301012 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001013 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301014 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001015 format == AUDIO_FORMAT_APTX ||
1016 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001017 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001018
1019 return false;
1020}
1021
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001022static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1023{
1024 struct listnode *node;
1025 struct audio_usecase *usecase;
1026
1027 list_for_each(node, &adev->usecase_list) {
1028 usecase = node_to_item(node, struct audio_usecase, list);
1029 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1030 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1031 return false;
1032 }
1033 }
1034
1035 return true;
1036}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001037static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1038{
1039 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001040 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001041 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1042}
1043
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001044static inline bool is_valid_volume(float left, float right)
1045{
1046 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1047}
1048
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301049static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301050{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301051 ALOGV("%s", __func__);
1052 audio_route_apply_and_update_path(adev->audio_route,
1053 "asrc-mode");
1054 adev->asrc_mode_enabled = true;
1055}
1056
1057static void disable_asrc_mode(struct audio_device *adev)
1058{
1059 ALOGV("%s", __func__);
1060 audio_route_reset_and_update_path(adev->audio_route,
1061 "asrc-mode");
1062 adev->asrc_mode_enabled = false;
1063}
1064
Saurav Kumarc1411662020-10-14 10:50:45 +05301065static void check_and_configure_headphone(struct audio_device *adev,
1066 struct audio_usecase *uc_info,
1067 snd_device_t snd_device)
1068{
1069 struct listnode *node;
1070 struct audio_usecase *usecase;
1071 int new_backend_idx, usecase_backend_idx;
1072 bool spkr_hph_single_be_native_concurrency;
1073
1074 new_backend_idx = platform_get_backend_index(snd_device);
1075 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001076 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1077 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301078 list_for_each(node, &adev->usecase_list) {
1079 usecase = node_to_item(node, struct audio_usecase, list);
1080 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1081 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1082 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1083 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1084 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1085 disable_audio_route(adev, usecase);
1086 disable_snd_device(adev, usecase->out_snd_device);
1087 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301088 platform_check_and_set_codec_backend_cfg(adev, usecase,
1089 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301090 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001091 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301092 }
1093 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001094 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1095 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1096 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1097 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1098 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1099 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1100 platform_check_and_set_codec_backend_cfg(adev, usecase,
1101 usecase->out_snd_device);
1102 }
1103 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301104 }
1105 }
1106}
1107
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301108/*
1109 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1110 * 44.1 or Native DSD backends are enabled for any of current use case.
1111 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1112 * - Disable current mix path use case(Headphone backend) and re-enable it with
1113 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1114 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1115 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301116static void check_and_set_asrc_mode(struct audio_device *adev,
1117 struct audio_usecase *uc_info,
1118 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301119{
1120 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301121 int i, num_new_devices = 0;
1122 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1123 /*
1124 *Split snd device for new combo use case
1125 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1126 */
1127 if (platform_split_snd_device(adev->platform,
1128 snd_device,
1129 &num_new_devices,
1130 split_new_snd_devices) == 0) {
1131 for (i = 0; i < num_new_devices; i++)
1132 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1133 } else {
1134 int new_backend_idx = platform_get_backend_index(snd_device);
1135 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1136 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1137 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1138 !adev->asrc_mode_enabled) {
1139 struct listnode *node = NULL;
1140 struct audio_usecase *uc = NULL;
1141 struct stream_out *curr_out = NULL;
1142 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1143 int i, num_devices, ret = 0;
1144 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301145
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301146 list_for_each(node, &adev->usecase_list) {
1147 uc = node_to_item(node, struct audio_usecase, list);
1148 curr_out = (struct stream_out*) uc->stream.out;
1149 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1150 /*
1151 *Split snd device for existing combo use case
1152 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1153 */
1154 ret = platform_split_snd_device(adev->platform,
1155 uc->out_snd_device,
1156 &num_devices,
1157 split_snd_devices);
1158 if (ret < 0 || num_devices == 0) {
1159 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1160 split_snd_devices[0] = uc->out_snd_device;
1161 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001162 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301163 for (i = 0; i < num_devices; i++) {
1164 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1165 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1166 if((new_backend_idx == HEADPHONE_BACKEND) &&
1167 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1168 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001169 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301170 __func__);
1171 enable_asrc_mode(adev);
1172 break;
1173 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1174 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1175 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001176 ALOGV("%s: 48K stream detected, disabling and enabling it \
1177 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301178 disable_audio_route(adev, uc);
1179 disable_snd_device(adev, uc->out_snd_device);
1180 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1181 if (new_backend_idx == DSD_NATIVE_BACKEND)
1182 audio_route_apply_and_update_path(adev->audio_route,
1183 "hph-true-highquality-mode");
1184 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1185 (curr_out->bit_width >= 24))
1186 audio_route_apply_and_update_path(adev->audio_route,
1187 "hph-highquality-mode");
1188 enable_asrc_mode(adev);
1189 enable_snd_device(adev, uc->out_snd_device);
1190 enable_audio_route(adev, uc);
1191 break;
1192 }
1193 }
1194 // reset split devices count
1195 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001196 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301197 if (adev->asrc_mode_enabled)
1198 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301199 }
1200 }
1201 }
1202}
1203
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1205 struct audio_effect_config effect_config,
1206 unsigned int param_value)
1207{
1208 char mixer_ctl_name[] = "Audio Effect";
1209 struct mixer_ctl *ctl;
1210 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001211 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001212
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001213 if (in == NULL) {
1214 ALOGE("%s: active input stream is NULL", __func__);
1215 return -EINVAL;
1216 }
1217
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001218 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1219 if (!ctl) {
1220 ALOGE("%s: Could not get mixer ctl - %s",
1221 __func__, mixer_ctl_name);
1222 return -EINVAL;
1223 }
1224
1225 set_values[0] = 1; //0:Rx 1:Tx
1226 set_values[1] = in->app_type_cfg.app_type;
1227 set_values[2] = (long)effect_config.module_id;
1228 set_values[3] = (long)effect_config.instance_id;
1229 set_values[4] = (long)effect_config.param_id;
1230 set_values[5] = param_value;
1231
1232 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1233
1234 return 0;
1235
1236}
1237
1238static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1239 int effect_type, unsigned int *param_value)
1240{
1241 int ret = 0;
1242 struct audio_effect_config other_effect_config;
1243 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001244 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001245
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001246 if (in == NULL) {
1247 ALOGE("%s: active input stream is NULL", __func__);
1248 return -EINVAL;
1249 }
1250
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001251 usecase = get_usecase_from_list(adev, in->usecase);
1252 if (!usecase)
1253 return -EINVAL;
1254
1255 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1256 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1257 if (ret < 0) {
1258 ALOGE("%s Failed to get effect params %d", __func__, ret);
1259 return ret;
1260 }
1261
1262 if (module_id == other_effect_config.module_id) {
1263 //Same module id for AEC/NS. Values need to be combined
1264 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1265 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1266 *param_value |= other_effect_config.param_value;
1267 }
1268 }
1269
1270 return ret;
1271}
1272
1273static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301274{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001275 struct audio_effect_config effect_config;
1276 struct audio_usecase *usecase = NULL;
1277 int ret = 0;
1278 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001279 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001280
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001281 if(!voice_extn_is_dynamic_ecns_enabled())
1282 return ENOSYS;
1283
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001284 if (!in) {
1285 ALOGE("%s: Invalid input stream", __func__);
1286 return -EINVAL;
1287 }
1288
1289 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1290
1291 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001292 if (usecase == NULL) {
1293 ALOGE("%s: Could not find the usecase (%d) in the list",
1294 __func__, in->usecase);
1295 return -EINVAL;
1296 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001297
1298 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1299 if (ret < 0) {
1300 ALOGE("%s Failed to get module id %d", __func__, ret);
1301 return ret;
1302 }
1303 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1304 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1305
1306 if(enable)
1307 param_value = effect_config.param_value;
1308
1309 /*Special handling for AEC & NS effects Param values need to be
1310 updated if module ids are same*/
1311
1312 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1313 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1314 if (ret < 0)
1315 return ret;
1316 }
1317
1318 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1319
1320 return ret;
1321}
1322
1323static void check_and_enable_effect(struct audio_device *adev)
1324{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001325 if(!voice_extn_is_dynamic_ecns_enabled())
1326 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001327
Eric Laurent637e2d42018-11-15 12:24:31 -08001328 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001329
Eric Laurent637e2d42018-11-15 12:24:31 -08001330 if (in != NULL && !in->standby) {
1331 if (in->enable_aec)
1332 enable_disable_effect(adev, EFFECT_AEC, true);
1333
1334 if (in->enable_ns &&
1335 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1336 enable_disable_effect(adev, EFFECT_NS, true);
1337 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001338 }
1339}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001340
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001341int pcm_ioctl(struct pcm *pcm, int request, ...)
1342{
1343 va_list ap;
1344 void * arg;
1345 int pcm_fd = *(int*)pcm;
1346
1347 va_start(ap, request);
1348 arg = va_arg(ap, void *);
1349 va_end(ap);
1350
1351 return ioctl(pcm_fd, request, arg);
1352}
1353
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001354int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001355 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001358 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301359 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001361 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301362 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001363
1364 if (usecase == NULL)
1365 return -EINVAL;
1366
1367 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1368
Carter Hsu2e429db2019-05-14 18:50:52 +08001369 if (usecase->type == PCM_CAPTURE) {
1370 struct stream_in *in = usecase->stream.in;
1371 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001373
1374 if (in) {
1375 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001376 list_init(&out_devices);
1377 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001378 struct listnode *node;
1379 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1380 USECASE_AUDIO_PLAYBACK_VOIP);
1381 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001382 assign_devices(&out_devices,
1383 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001384 } else if (adev->primary_output &&
1385 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001386 assign_devices(&out_devices,
1387 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001388 } else {
1389 list_for_each(node, &adev->usecase_list) {
1390 uinfo = node_to_item(node, struct audio_usecase, list);
1391 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001392 assign_devices(&out_devices,
1393 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001394 break;
1395 }
1396 }
1397 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001398
1399 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001400 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301401 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001402 }
1403 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001404 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1405 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1406 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001407 snd_device = usecase->in_snd_device;
1408 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001410 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001411
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001412 if (usecase->type == PCM_CAPTURE) {
1413 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1414 platform_set_fluence_nn_state(adev->platform, true);
1415 ALOGD("%s: set fluence nn capture state", __func__);
1416 }
1417 }
1418
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001419#ifdef DS1_DOLBY_DAP_ENABLED
1420 audio_extn_dolby_set_dmid(adev);
1421 audio_extn_dolby_set_endpoint(adev);
1422#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001423 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001424 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301425 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001426 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001427 if (audio_extn_is_maxx_audio_enabled())
1428 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301429 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001430 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1431 out = usecase->stream.out;
1432 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301433 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1434 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301435
1436 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001437 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1438 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1439 adev->fluence_nn_usecase_id = usecase->id;
1440 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1441 }
1442 }
1443
1444 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301445 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001446 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301447 ALOGD("%s: set custom mtmx params v1", __func__);
1448 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1449 }
1450 } else {
1451 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1452 }
Manish Dewangan58229382017-02-02 15:48:41 +05301453
Andy Hung756ecc12018-10-19 17:47:12 -07001454 // we shouldn't truncate mixer_path
1455 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1456 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1457 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001458 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001459 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301460 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1461 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1462 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1463 if (parms) {
1464 audio_extn_fm_set_parameters(adev, parms);
1465 str_parms_destroy(parms);
1466 }
1467 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468 ALOGV("%s: exit", __func__);
1469 return 0;
1470}
1471
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001472int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001473 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001476 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301477 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001478
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301479 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001480 return -EINVAL;
1481
1482 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301483 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001484 snd_device = usecase->in_snd_device;
1485 else
1486 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001487
1488 /* disable island and power mode on supported device for voice call */
1489 if (usecase->type == VOICE_CALL) {
1490 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1491 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1492 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1493 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1494 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1495 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001496 if (voice_is_lte_call_active(adev))
1497 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001498 ALOGD("%s: disable island cfg and power mode in voice tx path",
1499 __func__);
1500 }
1501 }
1502 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1503 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1504 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1505 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1506 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1507 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1508 ALOGD("%s: disable island cfg and power mode in voice rx path",
1509 __func__);
1510 }
1511 }
1512 }
1513
Andy Hung756ecc12018-10-19 17:47:12 -07001514 // we shouldn't truncate mixer_path
1515 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1516 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1517 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001518 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001519 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001520 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001521 if (usecase->type == PCM_CAPTURE) {
1522 struct stream_in *in = usecase->stream.in;
1523 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001524 struct listnode out_devices;
1525 list_init(&out_devices);
1526 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001527 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301528 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001529 }
1530 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001531 if (usecase->id == adev->fluence_nn_usecase_id) {
1532 platform_set_fluence_nn_state(adev->platform, false);
1533 adev->fluence_nn_usecase_id = USECASE_INVALID;
1534 ALOGD("%s: reset fluence nn capture state", __func__);
1535 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001536 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301537 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301538
1539 if (usecase->type == PCM_CAPTURE) {
1540 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001541 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301542 ALOGD("%s: reset custom mtmx params v1", __func__);
1543 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1544 }
1545 } else {
1546 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1547 }
1548
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001549 if ((usecase->type == PCM_PLAYBACK) &&
1550 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301551 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 ALOGV("%s: exit", __func__);
1554 return 0;
1555}
1556
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001557int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001558 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301560 int i, num_devices = 0;
1561 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001562 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1563
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001564 if (snd_device < SND_DEVICE_MIN ||
1565 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001566 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001567 return -EINVAL;
1568 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001569
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001570 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001571 ALOGE("%s: Invalid sound device returned", __func__);
1572 return -EINVAL;
1573 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001574
1575 adev->snd_dev_ref_cnt[snd_device]++;
1576
1577 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1578 (platform_split_snd_device(adev->platform,
1579 snd_device,
1580 &num_devices,
1581 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001582 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001583 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001584 /* Set backend config for A2DP to ensure slimbus configuration
1585 is correct if A2DP is already active and backend is closed
1586 and re-opened */
1587 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1588 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 return 0;
1590 }
1591
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001592 if (audio_extn_spkr_prot_is_enabled())
1593 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001594
Aalique Grahame22e49102018-12-18 14:23:57 -08001595 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1596
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001597 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1598 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001599 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1600 goto err;
1601 }
1602 audio_extn_dev_arbi_acquire(snd_device);
1603 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001604 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001605 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001606 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001607 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001608 } else if (platform_split_snd_device(adev->platform,
1609 snd_device,
1610 &num_devices,
1611 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301612 for (i = 0; i < num_devices; i++) {
1613 enable_snd_device(adev, new_snd_devices[i]);
1614 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001615 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001616 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001617 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301618
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001619 /* enable island and power mode on supported device */
1620 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1621 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1622 platform_set_island_cfg_on_device(adev, snd_device, true);
1623 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001624 if (voice_is_lte_call_active(adev) &&
1625 (snd_device >= SND_DEVICE_IN_BEGIN &&
1626 snd_device < SND_DEVICE_IN_END))
1627 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001628 ALOGD("%s: enable island cfg and power mode on: %s",
1629 __func__, device_name);
1630 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301631
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301632 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301633
1634 struct audio_usecase *usecase;
1635 struct listnode *node;
1636 /* Disable SCO Devices and enable handset mic for active input stream */
1637 list_for_each(node, &adev->usecase_list) {
1638 usecase = node_to_item(node, struct audio_usecase, list);
1639 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1640 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1641 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1642 reassign_device_list(&usecase->stream.in->device_list,
1643 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1644 select_devices(adev, usecase->id);
1645 }
1646 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301647 if (audio_extn_a2dp_start_playback() < 0) {
1648 ALOGE(" fail to configure A2dp Source control path ");
1649 goto err;
1650 } else {
1651 adev->a2dp_started = true;
1652 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001653 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001654
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001655 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1656 (audio_extn_a2dp_start_capture() < 0)) {
1657 ALOGE(" fail to configure A2dp Sink control path ");
1658 goto err;
1659 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301660
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001661 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1662 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1663 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1664 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1665 ALOGE(" fail to configure sco control path ");
1666 goto err;
1667 }
Zhou Song12c29502019-03-16 10:37:18 +08001668 }
1669
Zhou Song331c8e52019-08-26 14:16:12 +08001670 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001671 /* due to the possibility of calibration overwrite between listen
1672 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001673 audio_extn_sound_trigger_update_device_status(snd_device,
1674 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301675 audio_extn_listen_update_device_status(snd_device,
1676 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001677 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001678 audio_extn_sound_trigger_update_device_status(snd_device,
1679 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301680 audio_extn_listen_update_device_status(snd_device,
1681 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001682 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001683 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001684 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001685 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301686
1687 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1688 !adev->native_playback_enabled &&
1689 audio_is_true_native_stream_active(adev)) {
1690 ALOGD("%s: %d: napb: enabling native mode in hardware",
1691 __func__, __LINE__);
1692 audio_route_apply_and_update_path(adev->audio_route,
1693 "true-native-mode");
1694 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301695 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301696 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1697 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001698 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001699 ALOGD("%s: init ec ref loopback", __func__);
1700 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1701 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001704err:
1705 adev->snd_dev_ref_cnt[snd_device]--;
1706 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707}
1708
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001709int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001710 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301712 int i, num_devices = 0;
1713 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001714 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1715
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001716 if (snd_device < SND_DEVICE_MIN ||
1717 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001718 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001719 return -EINVAL;
1720 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001721
1722 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1723 ALOGE("%s: Invalid sound device returned", __func__);
1724 return -EINVAL;
1725 }
1726
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1728 ALOGE("%s: device ref cnt is already 0", __func__);
1729 return -EINVAL;
1730 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001731
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001732 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001733
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001734
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001735 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001736 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301737
Aalique Grahame22e49102018-12-18 14:23:57 -08001738 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1739
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001740 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1741 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001742 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001743
1744 // when speaker device is disabled, reset swap.
1745 // will be renabled on usecase start
1746 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001747 } else if (platform_split_snd_device(adev->platform,
1748 snd_device,
1749 &num_devices,
1750 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301751 for (i = 0; i < num_devices; i++) {
1752 disable_snd_device(adev, new_snd_devices[i]);
1753 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001754 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001755 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001756 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001757 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001758
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301759 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301760 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301761 adev->a2dp_started = false;
1762 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001763 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001764 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001765 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301766 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001767 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301768 adev->native_playback_enabled) {
1769 ALOGD("%s: %d: napb: disabling native mode in hardware",
1770 __func__, __LINE__);
1771 audio_route_reset_and_update_path(adev->audio_route,
1772 "true-native-mode");
1773 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001774 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301775 adev->asrc_mode_enabled) {
1776 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301777 disable_asrc_mode(adev);
1778 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001779 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301780 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001781 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001782 ALOGD("%s: deinit ec ref loopback", __func__);
1783 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1784 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001785
1786 audio_extn_utils_release_snd_device(snd_device);
1787 } else {
1788 if (platform_split_snd_device(adev->platform,
1789 snd_device,
1790 &num_devices,
1791 new_snd_devices) == 0) {
1792 for (i = 0; i < num_devices; i++) {
1793 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1794 }
1795 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 return 0;
1799}
1800
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001801/*
1802 legend:
1803 uc - existing usecase
1804 new_uc - new usecase
1805 d1, d11, d2 - SND_DEVICE enums
1806 a1, a2 - corresponding ANDROID device enums
1807 B1, B2 - backend strings
1808
1809case 1
1810 uc->dev d1 (a1) B1
1811 new_uc->dev d1 (a1), d2 (a2) B1, B2
1812
1813 resolution: disable and enable uc->dev on d1
1814
1815case 2
1816 uc->dev d1 (a1) B1
1817 new_uc->dev d11 (a1) B1
1818
1819 resolution: need to switch uc since d1 and d11 are related
1820 (e.g. speaker and voice-speaker)
1821 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1822
1823case 3
1824 uc->dev d1 (a1) B1
1825 new_uc->dev d2 (a2) B2
1826
1827 resolution: no need to switch uc
1828
1829case 4
1830 uc->dev d1 (a1) B1
1831 new_uc->dev d2 (a2) B1
1832
1833 resolution: disable enable uc-dev on d2 since backends match
1834 we cannot enable two streams on two different devices if they
1835 share the same backend. e.g. if offload is on speaker device using
1836 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1837 using the same backend, offload must also be switched to voice-handset.
1838
1839case 5
1840 uc->dev d1 (a1) B1
1841 new_uc->dev d1 (a1), d2 (a2) B1
1842
1843 resolution: disable enable uc-dev on d2 since backends match
1844 we cannot enable two streams on two different devices if they
1845 share the same backend.
1846
1847case 6
1848 uc->dev d1 (a1) B1
1849 new_uc->dev d2 (a1) B2
1850
1851 resolution: no need to switch
1852
1853case 7
1854 uc->dev d1 (a1), d2 (a2) B1, B2
1855 new_uc->dev d1 (a1) B1
1856
1857 resolution: no need to switch
1858
Zhou Song4ba65882018-07-09 14:48:07 +08001859case 8
1860 uc->dev d1 (a1) B1
1861 new_uc->dev d11 (a1), d2 (a2) B1, B2
1862 resolution: compared to case 1, for this case, d1 and d11 are related
1863 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301864
1865case 9
1866 uc->dev d1 (a1), d2(a2) B1 B2
1867 new_uc->dev d1 (a1), d22 (a2) B1, B2
1868 resolution: disable enable uc-dev on d2 since backends match
1869 we cannot enable two streams on two different devices if they
1870 share the same backend. This is special case for combo use case
1871 with a2dp and sco devices which uses same backend.
1872 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001873*/
1874static snd_device_t derive_playback_snd_device(void * platform,
1875 struct audio_usecase *uc,
1876 struct audio_usecase *new_uc,
1877 snd_device_t new_snd_device)
1878{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001879 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001880
1881 snd_device_t d1 = uc->out_snd_device;
1882 snd_device_t d2 = new_snd_device;
1883
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001884 list_init(&a1);
1885 list_init(&a2);
1886
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301887 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301888 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001889 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1890 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301891 break;
1892 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001893 assign_devices(&a1, &uc->stream.out->device_list);
1894 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301895 break;
1896 }
1897
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001898 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001899 if (!compare_devices(&a1, &a2) &&
1900 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001901 snd_device_t d3[2];
1902 int num_devices = 0;
1903 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001904 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001905 &num_devices,
1906 d3);
1907 if (ret < 0) {
1908 if (ret != -ENOSYS) {
1909 ALOGW("%s failed to split snd_device %d",
1910 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001911 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001912 }
1913 goto end;
1914 }
1915
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001916 if (platform_check_backends_match(d3[0], d3[1])) {
1917 return d2; // case 5
1918 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301919 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1920 platform_check_backends_match(d1, d2))
1921 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001922 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301923 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001924 // check if d1 is related to any of d3's
1925 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001926 return d1; // case 1
1927 else
1928 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001929 }
1930 } else {
1931 if (platform_check_backends_match(d1, d2)) {
1932 return d2; // case 2, 4
1933 } else {
1934 return d1; // case 6, 3
1935 }
1936 }
1937
Zhenlin Lian4f947842022-05-14 15:50:52 +05301938 clear_devices(&a1);
1939 clear_devices(&a2);
1940
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001941end:
1942 return d2; // return whatever was calculated before.
1943}
1944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001945static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301946 struct audio_usecase *uc_info,
1947 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948{
1949 struct listnode *node;
1950 struct audio_usecase *usecase;
1951 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301952 snd_device_t uc_derive_snd_device;
1953 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001954 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1955 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001956 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301957 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001958 /*
1959 * This function is to make sure that all the usecases that are active on
1960 * the hardware codec backend are always routed to any one device that is
1961 * handled by the hardware codec.
1962 * For example, if low-latency and deep-buffer usecases are currently active
1963 * on speaker and out_set_parameters(headset) is received on low-latency
1964 * output, then we have to make sure deep-buffer is also switched to headset,
1965 * because of the limitation that both the devices cannot be enabled
1966 * at the same time as they share the same backend.
1967 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001968 /*
1969 * This call is to check if we need to force routing for a particular stream
1970 * If there is a backend configuration change for the device when a
1971 * new stream starts, then ADM needs to be closed and re-opened with the new
1972 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001973 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001974 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001975 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1976 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301977 /* For a2dp device reconfigure all active sessions
1978 * with new AFE encoder format based on a2dp state
1979 */
1980 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301981 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1982 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301983 audio_extn_a2dp_is_force_device_switch()) {
1984 force_routing = true;
1985 force_restart_session = true;
1986 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001987
1988 /*
1989 * Island cfg and power mode config needs to set before AFE port start.
1990 * Set force routing in case of voice device was enable before.
1991 */
1992 if (uc_info->type == VOICE_CALL &&
1993 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001994 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001995 platform_check_and_update_island_power_status(adev->platform,
1996 uc_info,
1997 snd_device)) {
1998 force_routing = true;
1999 ALOGD("%s:becf: force routing %d for power mode supported device",
2000 __func__, force_routing);
2001 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302002 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2003
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002004 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002005 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002006 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002007 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2008 switch_device[i] = false;
2009
2010 list_for_each(node, &adev->usecase_list) {
2011 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002012
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302013 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2014 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302015 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302016 platform_get_snd_device_name(usecase->out_snd_device),
2017 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302018 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2019 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302020 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2021 usecase, uc_info, snd_device);
2022 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002023 (is_codec_backend_out_device_type(&usecase->device_list) ||
2024 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2025 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2026 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2027 is_a2dp_out_device_type(&usecase->device_list) ||
2028 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302029 ((force_restart_session) ||
2030 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302031 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2032 __func__, use_case_table[usecase->id],
2033 platform_get_snd_device_name(usecase->out_snd_device));
2034 disable_audio_route(adev, usecase);
2035 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302036 /* Enable existing usecase on derived playback device */
2037 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302038 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302039 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002040 }
2041 }
2042
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302043 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2044 num_uc_to_switch);
2045
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002047 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002048
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302049 /* Make sure the previous devices to be disabled first and then enable the
2050 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002051 list_for_each(node, &adev->usecase_list) {
2052 usecase = node_to_item(node, struct audio_usecase, list);
2053 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002054 /* Check if output sound device to be switched can be split and if any
2055 of the split devices match with derived sound device */
2056 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2057 &num_devices, split_snd_devices) == 0) {
2058 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2059 for (i = 0; i < num_devices; i++) {
2060 /* Disable devices that do not match with derived sound device */
2061 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2062 disable_snd_device(adev, split_snd_devices[i]);
2063 }
2064 } else {
2065 disable_snd_device(adev, usecase->out_snd_device);
2066 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002067 }
2068 }
2069
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002070 list_for_each(node, &adev->usecase_list) {
2071 usecase = node_to_item(node, struct audio_usecase, list);
2072 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002073 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2074 &num_devices, split_snd_devices) == 0) {
2075 /* Enable derived sound device only if it does not match with
2076 one of the split sound devices. This is because the matching
2077 sound device was not disabled */
2078 bool should_enable = true;
2079 for (i = 0; i < num_devices; i++) {
2080 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2081 should_enable = false;
2082 break;
2083 }
2084 }
2085 if (should_enable)
2086 enable_snd_device(adev, derive_snd_device[usecase->id]);
2087 } else {
2088 enable_snd_device(adev, derive_snd_device[usecase->id]);
2089 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002090 }
2091 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002092
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002093 /* Re-route all the usecases on the shared backend other than the
2094 specified usecase to new snd devices */
2095 list_for_each(node, &adev->usecase_list) {
2096 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302097 /* Update the out_snd_device only before enabling the audio route */
2098 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302099 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302100 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2101 use_case_table[usecase->id],
2102 platform_get_snd_device_name(usecase->out_snd_device));
2103 /* Update voc calibration before enabling Voice/VoIP route */
2104 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2105 status = platform_switch_voice_call_device_post(adev->platform,
2106 usecase->out_snd_device,
2107 platform_get_input_snd_device(
2108 adev->platform, NULL,
2109 &uc_info->device_list,
2110 usecase->type));
2111 enable_audio_route(adev, usecase);
2112 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2113 out_set_voip_volume(&usecase->stream.out->stream,
2114 usecase->stream.out->volume_l,
2115 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302116 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002117 }
2118 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002119 }
2120}
2121
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302122static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002123 struct audio_usecase *uc_info,
2124 snd_device_t snd_device)
2125{
2126 struct listnode *node;
2127 struct audio_usecase *usecase;
2128 bool switch_device[AUDIO_USECASE_MAX];
2129 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002130 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002131 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002132
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302133 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2134 snd_device);
2135 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302136
2137 /*
2138 * Make sure out devices is checked against out codec backend device and
2139 * also in devices against in codec backend. Checking out device against in
2140 * codec backend or vice versa causes issues.
2141 */
2142 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002143 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002144
2145 /*
2146 * Island cfg and power mode config needs to set before AFE port start.
2147 * Set force routing in case of voice device was enable before.
2148 */
2149
2150 if (uc_info->type == VOICE_CALL &&
2151 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002152 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002153 platform_check_and_update_island_power_status(adev->platform,
2154 uc_info,
2155 snd_device)) {
2156 force_routing = true;
2157 ALOGD("%s:becf: force routing %d for power mode supported device",
2158 __func__, force_routing);
2159 }
2160
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002161 /*
2162 * This function is to make sure that all the active capture usecases
2163 * are always routed to the same input sound device.
2164 * For example, if audio-record and voice-call usecases are currently
2165 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2166 * is received for voice call then we have to make sure that audio-record
2167 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2168 * because of the limitation that two devices cannot be enabled
2169 * at the same time if they share the same backend.
2170 */
2171 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2172 switch_device[i] = false;
2173
2174 list_for_each(node, &adev->usecase_list) {
2175 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302176 /*
2177 * TODO: Enhance below condition to handle BT sco/USB multi recording
2178 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302179
2180 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2181 (usecase->in_snd_device != snd_device || force_routing));
2182 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2183 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2184 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002185 ((backend_check_cond &&
2186 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002187 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002188 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002189 is_single_device_type_equal(&usecase->device_list,
2190 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302191 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002192 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002193 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302194 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002195 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002196 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002197 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002198 switch_device[usecase->id] = true;
2199 num_uc_to_switch++;
2200 }
2201 }
2202
2203 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002204 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002205
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302206 /* Make sure the previous devices to be disabled first and then enable the
2207 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002208 list_for_each(node, &adev->usecase_list) {
2209 usecase = node_to_item(node, struct audio_usecase, list);
2210 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002211 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002212 }
2213 }
2214
2215 list_for_each(node, &adev->usecase_list) {
2216 usecase = node_to_item(node, struct audio_usecase, list);
2217 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002218 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002219 }
2220 }
2221
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002222 /* Re-route all the usecases on the shared backend other than the
2223 specified usecase to new snd devices */
2224 list_for_each(node, &adev->usecase_list) {
2225 usecase = node_to_item(node, struct audio_usecase, list);
2226 /* Update the in_snd_device only before enabling the audio route */
2227 if (switch_device[usecase->id] ) {
2228 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302229 /* Update voc calibration before enabling Voice/VoIP route */
2230 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2231 snd_device_t voip_snd_device;
2232 voip_snd_device = platform_get_output_snd_device(adev->platform,
2233 usecase->stream.out,
2234 usecase->type);
2235 status = platform_switch_voice_call_device_post(adev->platform,
2236 voip_snd_device,
2237 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002238 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302239 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002240 }
2241 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002242 }
2243}
2244
Mingming Yin3a941d42016-02-17 18:08:05 -08002245static void reset_hdmi_sink_caps(struct stream_out *out) {
2246 int i = 0;
2247
2248 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2249 out->supported_channel_masks[i] = 0;
2250 }
2251 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2252 out->supported_formats[i] = 0;
2253 }
2254 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2255 out->supported_sample_rates[i] = 0;
2256 }
2257}
2258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002260static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261{
Mingming Yin3a941d42016-02-17 18:08:05 -08002262 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002263 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2264 out->extconn.cs.controller,
2265 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266
Mingming Yin3a941d42016-02-17 18:08:05 -08002267 reset_hdmi_sink_caps(out);
2268
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002269 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002270 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002271 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002272 out->extconn.cs.stream);
2273 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002274 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002275 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002276 }
2277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002280 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002281 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002282 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2283 case 6:
2284 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2285 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2286 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2287 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 break;
2291 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002292 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002293 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 break;
2295 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002296
2297 // check channel format caps
2298 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002299 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2300 out->extconn.cs.controller,
2301 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002302 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2303 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2304 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2305 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2306 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2307 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2308 }
2309
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002310 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2311 out->extconn.cs.controller,
2312 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002313 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2314 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2315 }
2316
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002317 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2318 out->extconn.cs.controller,
2319 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002320 ALOGV(":%s HDMI supports DTS format", __func__);
2321 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2322 }
2323
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002324 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2325 out->extconn.cs.controller,
2326 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002327 ALOGV(":%s HDMI supports DTS HD format", __func__);
2328 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2329 }
2330
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002331 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2332 out->extconn.cs.controller,
2333 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002334 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2335 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2336 }
2337
Mingming Yin3a941d42016-02-17 18:08:05 -08002338
2339 // check sample rate caps
2340 i = 0;
2341 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002342 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2343 out->extconn.cs.controller,
2344 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002345 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2346 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2347 }
2348 }
2349
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002350 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351}
2352
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002353static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2354 uint32_t *supported_sample_rates __unused,
2355 uint32_t max_rates __unused)
2356{
2357 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2358 supported_sample_rates,
2359 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302360 ssize_t i = 0;
2361
2362 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002363 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2364 supported_sample_rates[i]);
2365 }
2366 return count;
2367}
2368
2369static inline int read_usb_sup_channel_masks(bool is_playback,
2370 audio_channel_mask_t *supported_channel_masks,
2371 uint32_t max_masks)
2372{
2373 int channels = audio_extn_usb_get_max_channels(is_playback);
2374 int channel_count;
2375 uint32_t num_masks = 0;
2376 if (channels > MAX_HIFI_CHANNEL_COUNT)
2377 channels = MAX_HIFI_CHANNEL_COUNT;
2378
2379 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002380 // start from 2 channels as framework currently doesn't support mono.
2381 if (channels >= FCC_2) {
2382 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2383 }
2384 for (channel_count = FCC_2;
2385 channel_count <= channels && num_masks < max_masks;
2386 ++channel_count) {
2387 supported_channel_masks[num_masks++] =
2388 audio_channel_mask_for_index_assignment_from_count(channel_count);
2389 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002390 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002391 // For capture we report all supported channel masks from 1 channel up.
2392 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002393 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2394 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002395 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2396 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2397 if (channel_count <= FCC_2) {
2398 mask = audio_channel_in_mask_from_count(channel_count);
2399 supported_channel_masks[num_masks++] = mask;
2400 }
2401 const audio_channel_mask_t index_mask =
2402 audio_channel_mask_for_index_assignment_from_count(channel_count);
2403 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2404 supported_channel_masks[num_masks++] = index_mask;
2405 }
2406 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002407 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302408
vincenttewf51c94e2019-05-07 10:28:53 +08002409 for (size_t i = 0; i < num_masks; ++i) {
2410 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2411 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302412 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002413 return num_masks;
2414}
2415
2416static inline int read_usb_sup_formats(bool is_playback __unused,
2417 audio_format_t *supported_formats,
2418 uint32_t max_formats __unused)
2419{
2420 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2421 switch (bitwidth) {
2422 case 24:
2423 // XXX : usb.c returns 24 for s24 and s24_le?
2424 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2425 break;
2426 case 32:
2427 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2428 break;
2429 case 16:
2430 default :
2431 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2432 break;
2433 }
2434 ALOGV("%s: %s supported format %d", __func__,
2435 is_playback ? "P" : "C", bitwidth);
2436 return 1;
2437}
2438
2439static inline int read_usb_sup_params_and_compare(bool is_playback,
2440 audio_format_t *format,
2441 audio_format_t *supported_formats,
2442 uint32_t max_formats,
2443 audio_channel_mask_t *mask,
2444 audio_channel_mask_t *supported_channel_masks,
2445 uint32_t max_masks,
2446 uint32_t *rate,
2447 uint32_t *supported_sample_rates,
2448 uint32_t max_rates) {
2449 int ret = 0;
2450 int num_formats;
2451 int num_masks;
2452 int num_rates;
2453 int i;
2454
2455 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2456 max_formats);
2457 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2458 max_masks);
2459
2460 num_rates = read_usb_sup_sample_rates(is_playback,
2461 supported_sample_rates, max_rates);
2462
2463#define LUT(table, len, what, dflt) \
2464 for (i=0; i<len && (table[i] != what); i++); \
2465 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2466
2467 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2468 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2469 LUT(supported_sample_rates, num_rates, *rate, 0);
2470
2471#undef LUT
2472 return ret < 0 ? -EINVAL : 0; // HACK TBD
2473}
2474
Alexy Josephb1379942016-01-29 15:49:38 -08002475audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002476 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002477{
2478 struct audio_usecase *usecase;
2479 struct listnode *node;
2480
2481 list_for_each(node, &adev->usecase_list) {
2482 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002483 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002484 ALOGV("%s: usecase id %d", __func__, usecase->id);
2485 return usecase->id;
2486 }
2487 }
2488 return USECASE_INVALID;
2489}
2490
Alexy Josephb1379942016-01-29 15:49:38 -08002491struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002492 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002493{
2494 struct audio_usecase *usecase;
2495 struct listnode *node;
2496
2497 list_for_each(node, &adev->usecase_list) {
2498 usecase = node_to_item(node, struct audio_usecase, list);
2499 if (usecase->id == uc_id)
2500 return usecase;
2501 }
2502 return NULL;
2503}
2504
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302505/*
2506 * is a true native playback active
2507 */
2508bool audio_is_true_native_stream_active(struct audio_device *adev)
2509{
2510 bool active = false;
2511 int i = 0;
2512 struct listnode *node;
2513
2514 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2515 ALOGV("%s:napb: not in true mode or non hdphones device",
2516 __func__);
2517 active = false;
2518 goto exit;
2519 }
2520
2521 list_for_each(node, &adev->usecase_list) {
2522 struct audio_usecase *uc;
2523 uc = node_to_item(node, struct audio_usecase, list);
2524 struct stream_out *curr_out =
2525 (struct stream_out*) uc->stream.out;
2526
2527 if (curr_out && PCM_PLAYBACK == uc->type) {
2528 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2529 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2530 uc->id, curr_out->sample_rate,
2531 curr_out->bit_width,
2532 platform_get_snd_device_name(uc->out_snd_device));
2533
2534 if (is_offload_usecase(uc->id) &&
2535 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2536 active = true;
2537 ALOGD("%s:napb:native stream detected", __func__);
2538 }
2539 }
2540 }
2541exit:
2542 return active;
2543}
2544
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002545uint32_t adev_get_dsp_bit_width_enforce_mode()
2546{
2547 if (adev == NULL) {
2548 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2549 return 0;
2550 }
2551 return adev->dsp_bit_width_enforce_mode;
2552}
2553
2554static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2555{
2556 char value[PROPERTY_VALUE_MAX];
2557 int trial;
2558 uint32_t dsp_bit_width_enforce_mode = 0;
2559
2560 if (!mixer) {
2561 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2562 __func__);
2563 return 0;
2564 }
2565
2566 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2567 value, NULL) > 0) {
2568 trial = atoi(value);
2569 switch (trial) {
2570 case 16:
2571 dsp_bit_width_enforce_mode = 16;
2572 break;
2573 case 24:
2574 dsp_bit_width_enforce_mode = 24;
2575 break;
2576 case 32:
2577 dsp_bit_width_enforce_mode = 32;
2578 break;
2579 default:
2580 dsp_bit_width_enforce_mode = 0;
2581 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2582 break;
2583 }
2584 }
2585
2586 return dsp_bit_width_enforce_mode;
2587}
2588
2589static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2590 uint32_t enforce_mode,
2591 bool enable)
2592{
2593 struct mixer_ctl *ctl = NULL;
2594 const char *mixer_ctl_name = "ASM Bit Width";
2595 uint32_t asm_bit_width_mode = 0;
2596
2597 if (enforce_mode == 0) {
2598 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2599 return;
2600 }
2601
2602 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2603 if (!ctl) {
2604 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2605 __func__, mixer_ctl_name);
2606 return;
2607 }
2608
2609 if (enable)
2610 asm_bit_width_mode = enforce_mode;
2611 else
2612 asm_bit_width_mode = 0;
2613
2614 ALOGV("%s DSP bit width feature status is %d width=%d",
2615 __func__, enable, asm_bit_width_mode);
2616 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2617 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2618 asm_bit_width_mode);
2619
2620 return;
2621}
2622
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302623/*
2624 * if native DSD playback active
2625 */
2626bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2627{
2628 bool active = false;
2629 struct listnode *node = NULL;
2630 struct audio_usecase *uc = NULL;
2631 struct stream_out *curr_out = NULL;
2632
2633 list_for_each(node, &adev->usecase_list) {
2634 uc = node_to_item(node, struct audio_usecase, list);
2635 curr_out = (struct stream_out*) uc->stream.out;
2636
2637 if (curr_out && PCM_PLAYBACK == uc->type &&
2638 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2639 active = true;
2640 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302641 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302642 }
2643 }
2644 return active;
2645}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302646
2647static bool force_device_switch(struct audio_usecase *usecase)
2648{
2649 bool ret = false;
2650 bool is_it_true_mode = false;
2651
Zhou Song30f2c3e2018-02-08 14:02:15 +08002652 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302653 usecase->type == TRANSCODE_LOOPBACK_RX ||
2654 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002655 return false;
2656 }
2657
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002658 if(usecase->stream.out == NULL) {
2659 ALOGE("%s: stream.out is NULL", __func__);
2660 return false;
2661 }
2662
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302663 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002664 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002665 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2666 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302667 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2668 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2669 (!is_it_true_mode && adev->native_playback_enabled)){
2670 ret = true;
2671 ALOGD("napb: time to toggle native mode");
2672 }
2673 }
2674
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302675 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302676 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2677 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002678 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302679 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302680 ALOGD("Force a2dp device switch to update new encoder config");
2681 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002682 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302683
Florian Pfister1a84f312018-07-19 14:38:18 +02002684 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302685 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2686 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002687 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302688 return ret;
2689}
2690
Aalique Grahame22e49102018-12-18 14:23:57 -08002691static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2692{
2693 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2694}
2695
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302696bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2697{
2698 bool ret=false;
2699 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002700 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2701 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302702 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2703 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002704 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302705 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002706 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2707 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302708 ret = true;
2709
2710 return ret;
2711}
2712
2713bool is_a2dp_device(snd_device_t out_snd_device)
2714{
2715 bool ret=false;
2716 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2717 ret = true;
2718
2719 return ret;
2720}
2721
2722bool is_bt_soc_on(struct audio_device *adev)
2723{
2724 struct mixer_ctl *ctl;
2725 char *mixer_ctl_name = "BT SOC status";
2726 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2727 bool bt_soc_status = true;
2728 if (!ctl) {
2729 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2730 __func__, mixer_ctl_name);
2731 /*This is to ensure we dont break targets which dont have the kernel change*/
2732 return true;
2733 }
2734 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2735 ALOGD("BT SOC status: %d",bt_soc_status);
2736 return bt_soc_status;
2737}
2738
Zhou Song331c8e52019-08-26 14:16:12 +08002739static int configure_btsco_sample_rate(snd_device_t snd_device)
2740{
2741 struct mixer_ctl *ctl = NULL;
2742 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2743 char *rate_str = NULL;
2744 bool is_rx_dev = true;
2745
2746 if (is_btsco_device(snd_device, snd_device)) {
2747 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2748 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2749 if (!ctl_sr_tx || !ctl_sr_rx) {
2750 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2751 if (!ctl_sr)
2752 return -ENOSYS;
2753 }
2754
2755 switch (snd_device) {
2756 case SND_DEVICE_OUT_BT_SCO:
2757 rate_str = "KHZ_8";
2758 break;
2759 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2760 case SND_DEVICE_IN_BT_SCO_MIC:
2761 rate_str = "KHZ_8";
2762 is_rx_dev = false;
2763 break;
2764 case SND_DEVICE_OUT_BT_SCO_WB:
2765 rate_str = "KHZ_16";
2766 break;
2767 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2768 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2769 rate_str = "KHZ_16";
2770 is_rx_dev = false;
2771 break;
2772 default:
2773 return 0;
2774 }
2775
2776 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2777 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2778 return -ENOSYS;
2779 }
2780 return 0;
2781}
2782
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302783int out_standby_l(struct audio_stream *stream);
2784
Eric Laurent637e2d42018-11-15 12:24:31 -08002785struct stream_in *adev_get_active_input(const struct audio_device *adev)
2786{
2787 struct listnode *node;
2788 struct stream_in *last_active_in = NULL;
2789
2790 /* Get last added active input.
2791 * TODO: We may use a priority mechanism to pick highest priority active source */
2792 list_for_each(node, &adev->usecase_list)
2793 {
2794 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2795 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2796 last_active_in = usecase->stream.in;
2797 }
2798
2799 return last_active_in;
2800}
2801
2802struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2803{
2804 struct listnode *node;
2805
2806 /* First check active inputs with voice communication source and then
2807 * any input if audio mode is in communication */
2808 list_for_each(node, &adev->usecase_list)
2809 {
2810 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2811 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2812 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2813 return usecase->stream.in;
2814 }
2815 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2816 return adev_get_active_input(adev);
2817
2818 return NULL;
2819}
2820
Carter Hsu2e429db2019-05-14 18:50:52 +08002821/*
2822 * Aligned with policy.h
2823 */
2824static inline int source_priority(int inputSource)
2825{
2826 switch (inputSource) {
2827 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2828 return 9;
2829 case AUDIO_SOURCE_CAMCORDER:
2830 return 8;
2831 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2832 return 7;
2833 case AUDIO_SOURCE_UNPROCESSED:
2834 return 6;
2835 case AUDIO_SOURCE_MIC:
2836 return 5;
2837 case AUDIO_SOURCE_ECHO_REFERENCE:
2838 return 4;
2839 case AUDIO_SOURCE_FM_TUNER:
2840 return 3;
2841 case AUDIO_SOURCE_VOICE_RECOGNITION:
2842 return 2;
2843 case AUDIO_SOURCE_HOTWORD:
2844 return 1;
2845 default:
2846 break;
2847 }
2848 return 0;
2849}
2850
2851static struct stream_in *get_priority_input(struct audio_device *adev)
2852{
2853 struct listnode *node;
2854 struct audio_usecase *usecase;
2855 int last_priority = 0, priority;
2856 struct stream_in *priority_in = NULL;
2857 struct stream_in *in;
2858
2859 list_for_each(node, &adev->usecase_list) {
2860 usecase = node_to_item(node, struct audio_usecase, list);
2861 if (usecase->type == PCM_CAPTURE) {
2862 in = usecase->stream.in;
2863 if (!in)
2864 continue;
2865 priority = source_priority(in->source);
2866
2867 if (priority > last_priority) {
2868 last_priority = priority;
2869 priority_in = in;
2870 }
2871 }
2872 }
2873 return priority_in;
2874}
2875
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002876int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002878 snd_device_t out_snd_device = SND_DEVICE_NONE;
2879 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002880 struct audio_usecase *usecase = NULL;
2881 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002882 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002883 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302884 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002885 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002886 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302888 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2889
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002890 usecase = get_usecase_from_list(adev, uc_id);
2891 if (usecase == NULL) {
2892 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2893 return -EINVAL;
2894 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002896 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002897 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002898 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002899 (usecase->type == ICC_CALL) ||
2900 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302901 if(usecase->stream.out == NULL) {
2902 ALOGE("%s: stream.out is NULL", __func__);
2903 return -EINVAL;
2904 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002905 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002906 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2907 uc_id);
2908 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2909 uc_id);
2910 } else {
2911 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302912 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002913 in_snd_device = platform_get_input_snd_device(adev->platform,
2914 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302915 &usecase->stream.out->device_list,
2916 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002917 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002918 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302919 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302920 if (usecase->stream.inout == NULL) {
2921 ALOGE("%s: stream.inout is NULL", __func__);
2922 return -EINVAL;
2923 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002924 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302925 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2926 stream_out.format = usecase->stream.inout->out_config.format;
2927 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302928 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002929 assign_devices(&usecase->device_list,
2930 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05302931 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302932 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2933 if (usecase->stream.inout == NULL) {
2934 ALOGE("%s: stream.inout is NULL", __func__);
2935 return -EINVAL;
2936 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302937 struct listnode out_devices;
2938 list_init(&out_devices);
2939 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2940 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002941 assign_devices(&usecase->device_list,
2942 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05302943 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002944 } else {
2945 /*
2946 * If the voice call is active, use the sound devices of voice call usecase
2947 * so that it would not result any device switch. All the usecases will
2948 * be switched to new device when select_devices() is called for voice call
2949 * usecase. This is to avoid switching devices for voice call when
2950 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002951 * choose voice call device only if the use case device is
2952 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002953 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002954 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002955 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002956 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002957 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2958 is_codec_backend_out_device_type(&usecase->device_list)) ||
2959 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2960 is_codec_backend_in_device_type(&usecase->device_list)) ||
2961 is_single_device_type_equal(&vc_usecase->device_list,
2962 AUDIO_DEVICE_OUT_HEARING_AID) ||
2963 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002964 AUDIO_DEVICE_IN_VOICE_CALL) ||
2965 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05302966 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
2967 is_single_device_type_equal(&vc_usecase->device_list,
2968 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
2969 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002970 AUDIO_DEVICE_IN_USB_HEADSET) &&
2971 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302972 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05302973 (is_single_device_type_equal(&usecase->device_list,
2974 AUDIO_DEVICE_IN_USB_HEADSET) &&
2975 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302976 (is_single_device_type_equal(&usecase->device_list,
2977 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2978 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002979 in_snd_device = vc_usecase->in_snd_device;
2980 out_snd_device = vc_usecase->out_snd_device;
2981 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002982 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002983 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002984 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002985 if ((voip_usecase != NULL) &&
2986 (usecase->type == PCM_PLAYBACK) &&
2987 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002988 out_snd_device_backend_match = platform_check_backends_match(
2989 voip_usecase->out_snd_device,
2990 platform_get_output_snd_device(
2991 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302992 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002993 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002994 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2995 (is_codec_backend_out_device_type(&usecase->device_list) ||
2996 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002997 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002998 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002999 in_snd_device = voip_usecase->in_snd_device;
3000 out_snd_device = voip_usecase->out_snd_device;
3001 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003002 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003003 hfp_ucid = audio_extn_hfp_get_usecase();
3004 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003005 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003006 in_snd_device = hfp_usecase->in_snd_device;
3007 out_snd_device = hfp_usecase->out_snd_device;
3008 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003009 }
3010 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303011 if (usecase->stream.out == NULL) {
3012 ALOGE("%s: stream.out is NULL", __func__);
3013 return -EINVAL;
3014 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003015 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003016 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003017 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003018 struct stream_out *voip_out = adev->primary_output;
3019 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003020 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003021 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3022 else
3023 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303024 usecase->stream.out,
3025 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003026 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003027
Eric Laurent637e2d42018-11-15 12:24:31 -08003028 if (voip_usecase)
3029 voip_out = voip_usecase->stream.out;
3030
3031 if (usecase->stream.out == voip_out && voip_in != NULL)
3032 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003033 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003034 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303035 if (usecase->stream.in == NULL) {
3036 ALOGE("%s: stream.in is NULL", __func__);
3037 return -EINVAL;
3038 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003039 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003040 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003041 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003042 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003043 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003044 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003045
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003046 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003047 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003048 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3049 USECASE_AUDIO_PLAYBACK_VOIP);
3050
Carter Hsu2e429db2019-05-14 18:50:52 +08003051 usecase->stream.in->enable_ec_port = false;
3052
Zhou Song503196b2021-07-23 17:31:05 +08003053 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3054 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003055 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003056 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003057 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003058 } else if (adev->primary_output &&
3059 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003060 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003061 } else {
3062 /* forcing speaker o/p device to get matching i/p pair
3063 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003064 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003065 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003066 priority_in = voip_in;
3067 } else {
3068 /* get the input with the highest priority source*/
3069 priority_in = get_priority_input(adev);
3070
Susan Wang727dd6b2021-03-26 11:28:59 -04003071 if (!priority_in ||
3072 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003073 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003074 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003075 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3076 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3077 }
3078 else
3079 in_snd_device = platform_get_input_snd_device(adev->platform,
3080 priority_in,
3081 &out_devices,
3082 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303083 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003084 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003085 }
3086 }
3087
3088 if (out_snd_device == usecase->out_snd_device &&
3089 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303090
3091 if (!force_device_switch(usecase))
3092 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 }
3094
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003095 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003096 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003097 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003098 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3099 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303100 }
3101
Aalique Grahame22e49102018-12-18 14:23:57 -08003102 if (out_snd_device != SND_DEVICE_NONE &&
3103 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3104 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3105 __func__,
3106 use_case_table[uc_id],
3107 adev->last_logged_snd_device[uc_id][0],
3108 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3109 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3110 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3111 -1,
3112 out_snd_device,
3113 platform_get_snd_device_name(out_snd_device),
3114 platform_get_snd_device_acdb_id(out_snd_device));
3115 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3116 }
3117 if (in_snd_device != SND_DEVICE_NONE &&
3118 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3119 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3120 __func__,
3121 use_case_table[uc_id],
3122 adev->last_logged_snd_device[uc_id][1],
3123 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3124 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3125 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3126 -1,
3127 in_snd_device,
3128 platform_get_snd_device_name(in_snd_device),
3129 platform_get_snd_device_acdb_id(in_snd_device));
3130 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3131 }
3132
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 /*
3135 * Limitation: While in call, to do a device switch we need to disable
3136 * and enable both RX and TX devices though one of them is same as current
3137 * device.
3138 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003139 if ((usecase->type == VOICE_CALL) &&
3140 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3141 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003142 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003143 }
3144
3145 if (((usecase->type == VOICE_CALL) ||
3146 (usecase->type == VOIP_CALL)) &&
3147 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3148 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303149 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003150 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003151 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003152
3153 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303154 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003155 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003156 }
3157
Aalique Grahame22e49102018-12-18 14:23:57 -08003158 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3159 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003160 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303161 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003162 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3163 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3164 else
3165 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303166 }
3167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003168 /* Disable current sound devices */
3169 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003170 disable_audio_route(adev, usecase);
3171 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303172 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3173 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 }
3175
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003176 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003177 disable_audio_route(adev, usecase);
3178 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 }
3180
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003181 /* Applicable only on the targets that has external modem.
3182 * New device information should be sent to modem before enabling
3183 * the devices to reduce in-call device switch time.
3184 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003185 if ((usecase->type == VOICE_CALL) &&
3186 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3187 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003188 status = platform_switch_voice_call_enable_device_config(adev->platform,
3189 out_snd_device,
3190 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003191 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003192
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003193 /* Enable new sound devices */
3194 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003195 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303196 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303197 if (platform_check_codec_asrc_support(adev->platform))
3198 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003199 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003200 /* Enable haptics device for haptic usecase */
3201 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3202 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 }
3204
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003205 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303206 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003207 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003208 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003209
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303210 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003211 status = platform_switch_voice_call_device_post(adev->platform,
3212 out_snd_device,
3213 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003214
sangwoo170731f2013-06-08 15:36:36 +09003215 usecase->in_snd_device = in_snd_device;
3216 usecase->out_snd_device = out_snd_device;
3217
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303218 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3219 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303220 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003221 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003222 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003223 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3224 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3225 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3226 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3227 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3228 /*
3229 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3230 * configured device sample rate, if not update the COPP rate to be equal to the
3231 * device sample rate, else open COPP at stream sample rate
3232 */
3233 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3234 usecase->stream.out->sample_rate,
3235 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303236 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303237 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3238 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303239 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003240 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3241 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303242 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3243 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3244 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3245 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3246 }
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003247 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003248 }
3249 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003250
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303251 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3252 struct stream_in *voip_in = get_voice_communication_input(adev);
3253 struct audio_usecase *voip_in_usecase = NULL;
3254 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3255 if (voip_in != NULL &&
3256 voip_in_usecase != NULL &&
3257 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3258 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3259 (voip_in_usecase->in_snd_device ==
3260 platform_get_input_snd_device(adev->platform, voip_in,
3261 &usecase->stream.out->device_list,usecase->type))) {
3262 /*
3263 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3264 * for enabling echo-reference-voip with correct port
3265 */
3266 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3267 disable_audio_route(adev, voip_in_usecase);
3268 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3269 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3270 enable_audio_route(adev, voip_in_usecase);
3271 }
3272 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303273 if (voice_extn_compress_voip_is_active(adev)) {
3274 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3275 USECASE_COMPRESS_VOIP_CALL);
3276 /*
3277 * If only compress voip input is opened voip out will be primary out.
3278 * Need to consider re-routing to select correct i/p pair
3279 */
3280 if ((voip_usecase != NULL) &&
3281 (usecase->type == PCM_PLAYBACK) &&
3282 (usecase->stream.out == voip_usecase->stream.out)) {
3283 in_snd_device = platform_get_input_snd_device(adev->platform,
3284 NULL,
3285 &usecase->stream.out->device_list,
3286 usecase->type);
3287 if (voip_usecase->in_snd_device != in_snd_device ) {
3288 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3289 __func__);
3290 disable_audio_route(adev, voip_usecase);
3291 disable_snd_device(adev, voip_usecase->in_snd_device);
3292 voip_usecase->in_snd_device = in_snd_device;
3293 voip_usecase->out_snd_device = usecase->out_snd_device;
3294 /* Route all TX usecase to Compress voip BE */
3295 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3296 enable_snd_device(adev, in_snd_device);
3297 /* Send Voice related calibration for RX /TX pair */
3298 status = platform_switch_voice_call_device_post(adev->platform,
3299 out_snd_device,
3300 in_snd_device);
3301 enable_audio_route(adev, voip_usecase);
3302 }
3303 }
3304 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303305
3306
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003307 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003308
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003309 /* If input stream is already running then effect needs to be
3310 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003311 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003312 check_and_enable_effect(adev);
3313
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003314 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003315 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303316 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003317 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3318
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003319 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303320 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003321 voice_extn_compress_voip_is_started(adev))
3322 voice_set_sidetone(adev, out_snd_device, true);
3323 }
3324
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003325 /* Applicable only on the targets that has external modem.
3326 * Enable device command should be sent to modem only after
3327 * enabling voice call mixer controls
3328 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003329 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003330 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3331 out_snd_device,
3332 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303333
3334 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003335 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303336 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003337 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303338 if (is_bt_soc_on(adev) == false){
3339 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003340 if (in->pcm != NULL)
3341 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303342 }
3343 }
3344 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3345 && usecase->stream.out->started) {
3346 if (is_bt_soc_on(adev) == false) {
3347 ALOGD("BT SCO/A2DP disconnected while in connection");
3348 out_standby_l(&usecase->stream.out->stream.common);
3349 }
3350 }
3351 } else if ((usecase->stream.out != NULL) &&
3352 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303353 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3354 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003355 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303356 usecase->stream.out->started) {
3357 if (is_bt_soc_on(adev) == false) {
3358 ALOGD("BT SCO/A2dp disconnected while in connection");
3359 out_standby_l(&usecase->stream.out->stream.common);
3360 }
3361 }
3362 }
3363
Yung Ti Su70cb8242018-06-22 17:38:47 +08003364 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003365 struct stream_out *voip_out = voip_usecase->stream.out;
3366 audio_extn_utils_send_app_type_gain(adev,
3367 voip_out->app_type_cfg.app_type,
3368 &voip_out->app_type_cfg.gain[0]);
3369 }
3370
Ajender Reddyb940b832021-07-07 11:51:42 +05303371 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 return status;
3374}
3375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376static int stop_input_stream(struct stream_in *in)
3377{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303378 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303380
3381 if (in == NULL) {
3382 ALOGE("%s: stream_in ptr is NULL", __func__);
3383 return -EINVAL;
3384 }
3385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003387 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388
Eric Laurent994a6932013-07-17 11:51:42 -07003389 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003390 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 uc_info = get_usecase_from_list(adev, in->usecase);
3392 if (uc_info == NULL) {
3393 ALOGE("%s: Could not find the usecase (%d) in the list",
3394 __func__, in->usecase);
3395 return -EINVAL;
3396 }
3397
Carter Hsu2e429db2019-05-14 18:50:52 +08003398 priority_in = get_priority_input(adev);
3399
Derek Chenea197282019-01-07 17:35:01 -08003400 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3401 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003402
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003403 /* Close in-call recording streams */
3404 voice_check_and_stop_incall_rec_usecase(adev, in);
3405
Eric Laurent150dbfe2013-02-27 14:31:02 -08003406 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003407 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003408
3409 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003410 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003412 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303413 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3414
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003415 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303416 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003417 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418
Carter Hsu2e429db2019-05-14 18:50:52 +08003419 if (priority_in == in) {
3420 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303421 if (priority_in) {
3422 if (is_usb_in_device_type(&priority_in->device_list)) {
3423 if (audio_extn_usb_connected(NULL))
3424 select_devices(adev, priority_in->usecase);
3425 } else {
3426 select_devices(adev, priority_in->usecase);
3427 }
3428 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003429 }
3430
Vatsal Buchac09ae062018-11-14 13:25:08 +05303431 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003432 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433 return ret;
3434}
3435
3436int start_input_stream(struct stream_in *in)
3437{
3438 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003439 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303441
3442 if (in == NULL) {
3443 ALOGE("%s: stream_in ptr is NULL", __func__);
3444 return -EINVAL;
3445 }
3446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003448 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003449 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450
Mingming Yin2664a5b2015-09-03 10:53:11 -07003451 if (get_usecase_from_list(adev, usecase) == NULL)
3452 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303453 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3454 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003455
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303456 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003457 CARD_STATUS_OFFLINE == adev->card_status ||
3458 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3459 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303460 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303461 goto error_config;
3462 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303463
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003464 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303465 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303466 ALOGE("%s: SCO profile is not ready, return error", __func__);
3467 ret = -EIO;
3468 goto error_config;
3469 }
3470 }
3471
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003472 /* Check if source matches incall recording usecase criteria */
3473 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3474 if (ret)
3475 goto error_config;
3476 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003477 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3478
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303479 if (audio_extn_cin_attached_usecase(in))
3480 audio_extn_cin_acquire_usecase(in);
3481
Mingming Yin2664a5b2015-09-03 10:53:11 -07003482 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3483 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3484 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003485 ret = -EINVAL;
3486 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003487 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003488
Eric Laurentb23d5282013-05-14 15:27:20 -07003489 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 if (in->pcm_device_id < 0) {
3491 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3492 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003493 ret = -EINVAL;
3494 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003498
3499 if (!uc_info) {
3500 ret = -ENOMEM;
3501 goto error_config;
3502 }
3503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 uc_info->id = in->usecase;
3505 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003506 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003507 list_init(&uc_info->device_list);
3508 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003509 uc_info->in_snd_device = SND_DEVICE_NONE;
3510 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003512 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003513 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303514 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3515 adev->perf_lock_opts,
3516 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003517 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518
Derek Chenea197282019-01-07 17:35:01 -08003519 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3520 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003521
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303522 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3523
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303524 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303525 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303526 if (ret)
3527 goto error_open;
3528 else
3529 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003530 }
3531
Haynes Mathew George16081042017-05-31 17:16:49 -07003532 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003533 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003534 ALOGE("%s: pcm stream not ready", __func__);
3535 goto error_open;
3536 }
3537 ret = pcm_start(in->pcm);
3538 if (ret < 0) {
3539 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3540 goto error_open;
3541 }
3542 } else {
3543 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3544 unsigned int pcm_open_retry_count = 0;
3545
Zhou Song62ea0282020-03-22 19:53:01 +08003546 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3547 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003548 flags |= PCM_MMAP | PCM_NOIRQ;
3549 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3550 } else if (in->realtime) {
3551 flags |= PCM_MMAP | PCM_NOIRQ;
3552 }
3553
Garmond Leunge2433c32017-09-28 21:51:22 -07003554 if (audio_extn_ffv_get_stream() == in) {
3555 ALOGD("%s: ffv stream, update pcm config", __func__);
3556 audio_extn_ffv_update_pcm_config(&config);
3557 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003558 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3559 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3560
3561 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003562 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003563 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003564 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003565 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303566 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303567 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3568 adev->card_status = CARD_STATUS_OFFLINE;
3569 in->card_status = CARD_STATUS_OFFLINE;
3570 ret = -EIO;
3571 goto error_open;
3572 }
3573
Haynes Mathew George16081042017-05-31 17:16:49 -07003574 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3575 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3576 if (in->pcm != NULL) {
3577 pcm_close(in->pcm);
3578 in->pcm = NULL;
3579 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003580 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003581 ret = -EIO;
3582 goto error_open;
3583 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003584 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003585 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3586 continue;
3587 }
3588 break;
3589 }
3590
3591 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003592 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003593 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003594 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003595 if (ret < 0) {
3596 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3597 pcm_close(in->pcm);
3598 in->pcm = NULL;
3599 goto error_open;
3600 }
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303601 if (in->flags == AUDIO_INPUT_FLAG_FAST)
3602 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003603 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003604 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003605 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003606 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003607 if (ret < 0) {
3608 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003609 pcm_close(in->pcm);
3610 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003611 goto error_open;
3612 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003613 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003614 }
3615
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003616 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003617 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3618 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003619
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003620 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303621 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3622
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303623done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003624 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303625 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303626 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303627 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003628 return ret;
3629
3630error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003631 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303632 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003634
Eric Laurentc8400632013-02-14 19:04:54 -08003635error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003636 if (audio_extn_cin_attached_usecase(in))
3637 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303638 /*
3639 * sleep 50ms to allow sufficient time for kernel
3640 * drivers to recover incases like SSR.
3641 */
3642 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003643 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303644 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003645 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646}
3647
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003648void lock_input_stream(struct stream_in *in)
3649{
3650 pthread_mutex_lock(&in->pre_lock);
3651 pthread_mutex_lock(&in->lock);
3652 pthread_mutex_unlock(&in->pre_lock);
3653}
3654
3655void lock_output_stream(struct stream_out *out)
3656{
3657 pthread_mutex_lock(&out->pre_lock);
3658 pthread_mutex_lock(&out->lock);
3659 pthread_mutex_unlock(&out->pre_lock);
3660}
3661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662/* must be called with out->lock locked */
3663static int send_offload_cmd_l(struct stream_out* out, int command)
3664{
3665 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3666
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003667 if (!cmd) {
3668 ALOGE("failed to allocate mem for command 0x%x", command);
3669 return -ENOMEM;
3670 }
3671
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 ALOGVV("%s %d", __func__, command);
3673
3674 cmd->cmd = command;
3675 list_add_tail(&out->offload_cmd_list, &cmd->node);
3676 pthread_cond_signal(&out->offload_cond);
3677 return 0;
3678}
3679
Gautam Manam14c198b2020-12-24 14:08:04 +05303680/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003681static void stop_compressed_output_l(struct stream_out *out)
3682{
Gautam Manam14c198b2020-12-24 14:08:04 +05303683 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303685 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003686
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003688 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003689 if (out->compr != NULL) {
3690 compress_stop(out->compr);
3691 while (out->offload_thread_blocked) {
3692 pthread_cond_wait(&out->cond, &out->lock);
3693 }
3694 }
3695}
3696
Varun Balaraje49253e2017-07-06 19:48:56 +05303697bool is_interactive_usecase(audio_usecase_t uc_id)
3698{
3699 unsigned int i;
3700 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3701 if (uc_id == interactive_usecases[i])
3702 return true;
3703 }
3704 return false;
3705}
3706
3707static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3708{
3709 audio_usecase_t ret_uc = USECASE_INVALID;
3710 unsigned int intract_uc_index;
3711 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3712
3713 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3714 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3715 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3716 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3717 ret_uc = interactive_usecases[intract_uc_index];
3718 break;
3719 }
3720 }
3721
3722 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3723 return ret_uc;
3724}
3725
3726static void free_interactive_usecase(struct audio_device *adev,
3727 audio_usecase_t uc_id)
3728{
3729 unsigned int interact_uc_index;
3730 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3731
3732 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3733 if (interactive_usecases[interact_uc_index] == uc_id) {
3734 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3735 break;
3736 }
3737 }
3738 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3739}
3740
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003741bool is_offload_usecase(audio_usecase_t uc_id)
3742{
3743 unsigned int i;
3744 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3745 if (uc_id == offload_usecases[i])
3746 return true;
3747 }
3748 return false;
3749}
3750
Dhananjay Kumarac341582017-02-23 23:42:25 +05303751static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003752{
vivek mehta446c3962015-09-14 10:57:35 -07003753 audio_usecase_t ret_uc = USECASE_INVALID;
3754 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003755 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003756 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303757 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003758 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3759 else
3760 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003761
vivek mehta446c3962015-09-14 10:57:35 -07003762 pthread_mutex_lock(&adev->lock);
3763 if (get_usecase_from_list(adev, ret_uc) != NULL)
3764 ret_uc = USECASE_INVALID;
3765 pthread_mutex_unlock(&adev->lock);
3766
3767 return ret_uc;
3768 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003769
3770 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003771 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3772 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3773 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3774 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003775 break;
3776 }
3777 }
vivek mehta446c3962015-09-14 10:57:35 -07003778
3779 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3780 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003781}
3782
3783static void free_offload_usecase(struct audio_device *adev,
3784 audio_usecase_t uc_id)
3785{
vivek mehta446c3962015-09-14 10:57:35 -07003786 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003787 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003788
3789 if (!adev->multi_offload_enable)
3790 return;
3791
3792 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3793 if (offload_usecases[offload_uc_index] == uc_id) {
3794 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003795 break;
3796 }
3797 }
3798 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3799}
3800
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003801static void *offload_thread_loop(void *context)
3802{
3803 struct stream_out *out = (struct stream_out *) context;
3804 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003805 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003807 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003808 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3810
3811 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003812 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003813 out->offload_state = OFFLOAD_STATE_IDLE;
3814 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003815 for (;;) {
3816 struct offload_cmd *cmd = NULL;
3817 stream_callback_event_t event;
3818 bool send_callback = false;
3819
3820 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3821 __func__, list_empty(&out->offload_cmd_list),
3822 out->offload_state);
3823 if (list_empty(&out->offload_cmd_list)) {
3824 ALOGV("%s SLEEPING", __func__);
3825 pthread_cond_wait(&out->offload_cond, &out->lock);
3826 ALOGV("%s RUNNING", __func__);
3827 continue;
3828 }
3829
3830 item = list_head(&out->offload_cmd_list);
3831 cmd = node_to_item(item, struct offload_cmd, node);
3832 list_remove(item);
3833
3834 ALOGVV("%s STATE %d CMD %d out->compr %p",
3835 __func__, out->offload_state, cmd->cmd, out->compr);
3836
3837 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3838 free(cmd);
3839 break;
3840 }
3841
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003842 // allow OFFLOAD_CMD_ERROR reporting during standby
3843 // this is needed to handle failures during compress_open
3844 // Note however that on a pause timeout, the stream is closed
3845 // and no offload usecase will be active. Therefore this
3846 // special case is needed for compress_open failures alone
3847 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3848 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003849 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003850 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003851 pthread_cond_signal(&out->cond);
3852 continue;
3853 }
3854 out->offload_thread_blocked = true;
3855 pthread_mutex_unlock(&out->lock);
3856 send_callback = false;
3857 switch(cmd->cmd) {
3858 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003859 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003860 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003861 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 send_callback = true;
3863 event = STREAM_CBK_EVENT_WRITE_READY;
3864 break;
3865 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003866 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303867 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003868 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303869 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003870 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303871 if (ret < 0)
3872 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303873 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303874 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003875 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003876 else
3877 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003878 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003879 (CARD_STATUS_OFFLINE == out->card_status ||
3880 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303881 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303882 pthread_mutex_lock(&out->lock);
3883 out->send_new_metadata = 1;
3884 out->send_next_track_params = true;
3885 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303886 event = STREAM_CBK_EVENT_DRAIN_READY;
3887 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3888 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303889 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003890 break;
3891 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003892 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003893 ret = compress_drain(out->compr);
3894 ALOGD("copl(%p):out of compress_drain", out);
3895 // EINTR check avoids drain interruption due to SSR
3896 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003897 (CARD_STATUS_OFFLINE == out->card_status ||
3898 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003899 send_callback = true;
3900 event = STREAM_CBK_EVENT_DRAIN_READY;
3901 } else
3902 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003903 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303904 case OFFLOAD_CMD_ERROR:
3905 ALOGD("copl(%p): sending error callback to AF", out);
3906 send_callback = true;
3907 event = STREAM_CBK_EVENT_ERROR;
3908 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003909 default:
3910 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3911 break;
3912 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003913 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003914 out->offload_thread_blocked = false;
3915 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003916 if (send_callback && out->client_callback) {
3917 ALOGVV("%s: sending client_callback event %d", __func__, event);
3918 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003919 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003920 free(cmd);
3921 }
3922
3923 pthread_cond_signal(&out->cond);
3924 while (!list_empty(&out->offload_cmd_list)) {
3925 item = list_head(&out->offload_cmd_list);
3926 list_remove(item);
3927 free(node_to_item(item, struct offload_cmd, node));
3928 }
3929 pthread_mutex_unlock(&out->lock);
3930
3931 return NULL;
3932}
3933
3934static int create_offload_callback_thread(struct stream_out *out)
3935{
3936 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3937 list_init(&out->offload_cmd_list);
3938 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3939 offload_thread_loop, out);
3940 return 0;
3941}
3942
3943static int destroy_offload_callback_thread(struct stream_out *out)
3944{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003945 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003946 stop_compressed_output_l(out);
3947 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3948
3949 pthread_mutex_unlock(&out->lock);
3950 pthread_join(out->offload_thread, (void **) NULL);
3951 pthread_cond_destroy(&out->offload_cond);
3952
3953 return 0;
3954}
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956static int stop_output_stream(struct stream_out *out)
3957{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303958 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 struct audio_usecase *uc_info;
3960 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003961 bool has_voip_usecase =
3962 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963
Eric Laurent994a6932013-07-17 11:51:42 -07003964 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003965 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 uc_info = get_usecase_from_list(adev, out->usecase);
3967 if (uc_info == NULL) {
3968 ALOGE("%s: Could not find the usecase (%d) in the list",
3969 __func__, out->usecase);
3970 return -EINVAL;
3971 }
3972
Zhou Songbaddf9f2020-11-20 13:57:39 +08003973 out->a2dp_muted = false;
3974
Derek Chenea197282019-01-07 17:35:01 -08003975 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3976 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003977
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003978 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303979 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003980 if (adev->visualizer_stop_output != NULL)
3981 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003982
3983 audio_extn_dts_remove_state_notifier_node(out->usecase);
3984
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003985 if (adev->offload_effects_stop_output != NULL)
3986 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003987 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3988 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3989 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003990 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003991
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003992 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3993 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003994 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003995 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003996
Eric Laurent150dbfe2013-02-27 14:31:02 -08003997 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003998 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003999
4000 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004001 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004002 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4003 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004
Aalique Grahame22e49102018-12-18 14:23:57 -08004005 audio_extn_extspk_update(adev->extspk);
4006
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004007 if (is_offload_usecase(out->usecase)) {
4008 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4009 adev->dsp_bit_width_enforce_mode,
4010 false);
4011 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004012 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004013 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4014 false);
4015
4016 if (ret != 0)
4017 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4018 /* default service interval was successfully updated,
4019 reopen USB backend with new service interval */
4020 ret = 0;
4021 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004022
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004023 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304024 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004025 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304026 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004027 ALOGV("Disable passthrough , reset mixer to pcm");
4028 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004029#ifdef AUDIO_GKI_ENABLED
4030 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4031 out->compr_config.codec->reserved[0] = 0;
4032#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004033 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004034#endif
Mingming Yin21854652016-04-13 11:54:02 -07004035 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004036 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4037 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004038
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304039 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004040 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304041 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304042
Manish Dewangan21a850a2017-08-14 12:03:55 +05304043 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004044 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4045 if (ret < 0)
4046 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4047 }
4048
Zhou Song642ec432020-12-23 16:11:10 +08004049 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004050 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004051 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004052 struct listnode *node;
4053 struct audio_usecase *usecase;
4054 list_for_each(node, &adev->usecase_list) {
4055 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004056 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4057 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304058 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004059 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004060 continue;
4061
4062 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4063 __func__, usecase->id, use_case_table[usecase->id],
4064 out->usecase, use_case_table[out->usecase]);
4065 select_devices(adev, usecase->id);
4066 }
4067 }
4068
Zhenlin Lian4f947842022-05-14 15:50:52 +05304069 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004070 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004071 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 return ret;
4073}
4074
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004075struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4076 unsigned int flags, unsigned int pcm_open_retry_count,
4077 struct pcm_config *config)
4078{
4079 struct pcm* pcm = NULL;
4080
4081 while (1) {
4082 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4083 if (pcm == NULL || !pcm_is_ready(pcm)) {
4084 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4085 if (pcm != NULL) {
4086 pcm_close(pcm);
4087 pcm = NULL;
4088 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004089 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004090 return NULL;
4091
Weiyin Jiang72197252019-10-09 11:49:32 +08004092 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004093 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4094 continue;
4095 }
4096 break;
4097 }
4098
4099 if (pcm_is_ready(pcm)) {
4100 int ret = pcm_prepare(pcm);
4101 if (ret < 0) {
4102 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4103 pcm_close(pcm);
4104 pcm = NULL;
4105 }
4106 }
4107
4108 return pcm;
4109}
4110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111int start_output_stream(struct stream_out *out)
4112{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 struct audio_usecase *uc_info;
4115 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004116 char mixer_ctl_name[128];
4117 struct mixer_ctl *ctl = NULL;
4118 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304119 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004120 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121
Haynes Mathew George380745d2017-10-04 15:27:45 -07004122 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004123 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4124 ret = -EINVAL;
4125 goto error_config;
4126 }
4127
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004128 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304129 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004130 get_device_types(&out->device_list), is_haptic_usecase);
4131
4132 bool is_speaker_active = compare_device_type(&out->device_list,
4133 AUDIO_DEVICE_OUT_SPEAKER);
4134 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4135 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304136
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304137 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004138 CARD_STATUS_OFFLINE == adev->card_status ||
4139 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304140 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304141 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004142 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304143 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304144
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004145 //Update incall music usecase to reflect correct voice session
4146 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4147 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4148 if (ret != 0) {
4149 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4150 __func__, ret);
4151 goto error_config;
4152 }
4153 }
4154
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004155 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004156 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004157 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304158 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304159 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004160 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304161 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4162 ret = -EAGAIN;
4163 goto error_config;
4164 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304165 }
4166 }
4167 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004168 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304169 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004170 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304171 //combo usecase just by pass a2dp
4172 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004173 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304174 } else {
4175 ALOGE("%s: SCO profile is not ready, return error", __func__);
4176 ret = -EAGAIN;
4177 goto error_config;
4178 }
4179 }
4180 }
4181
Eric Laurentb23d5282013-05-14 15:27:20 -07004182 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 if (out->pcm_device_id < 0) {
4184 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4185 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004186 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004187 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 }
4189
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004190 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004191 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4192 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004193 if (adev->haptic_pcm_device_id < 0) {
4194 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4195 __func__, adev->haptic_pcm_device_id, out->usecase);
4196 ret = -EINVAL;
4197 goto error_config;
4198 }
4199 }
4200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004202
4203 if (!uc_info) {
4204 ret = -ENOMEM;
4205 goto error_config;
4206 }
4207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 uc_info->id = out->usecase;
4209 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004210 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004211 list_init(&uc_info->device_list);
4212 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004213 uc_info->in_snd_device = SND_DEVICE_NONE;
4214 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004215
4216 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004217 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004218 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4219 /* USB backend is not reopened immediately.
4220 This is eventually done as part of select_devices */
4221 }
4222
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004223 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224
Wei Wangf7ca6c92017-11-21 14:51:20 -08004225 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304226 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4227 adev->perf_lock_opts,
4228 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304229
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004230 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304231 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304232 if (audio_extn_passthru_is_enabled() &&
4233 audio_extn_passthru_is_passthrough_stream(out)) {
4234 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304235 }
4236 }
4237
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004238 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004239 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304240 if (!a2dp_combo) {
4241 check_a2dp_restore_l(adev, out, false);
4242 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004243 struct listnode dev;
4244 list_init(&dev);
4245 assign_devices(&dev, &out->device_list);
4246 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4247 reassign_device_list(&out->device_list,
4248 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004249 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004250 reassign_device_list(&out->device_list,
4251 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304252 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004253 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304254 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304255 }
4256 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304257 select_devices(adev, out->usecase);
4258 if (is_a2dp_out_device_type(&out->device_list) &&
4259 !adev->a2dp_started) {
4260 if (is_speaker_active || is_speaker_safe_active) {
4261 struct listnode dev;
4262 list_init(&dev);
4263 assign_devices(&dev, &out->device_list);
4264 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4265 reassign_device_list(&out->device_list,
4266 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4267 else
4268 reassign_device_list(&out->device_list,
4269 AUDIO_DEVICE_OUT_SPEAKER, "");
4270 select_devices(adev, out->usecase);
4271 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304272 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304273 } else {
4274 ret = -EINVAL;
4275 goto error_open;
4276 }
4277 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304278 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004279
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004280 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4281 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004282 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004283 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004284
Derek Chenea197282019-01-07 17:35:01 -08004285 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4286 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004287
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004288 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4289 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004290
4291 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004292 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004293 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4294 ALOGE("%s: pcm stream not ready", __func__);
4295 goto error_open;
4296 }
4297 ret = pcm_start(out->pcm);
4298 if (ret < 0) {
4299 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4300 goto error_open;
4301 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004302 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004303 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004304 unsigned int flags = PCM_OUT;
4305 unsigned int pcm_open_retry_count = 0;
4306 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4307 flags |= PCM_MMAP | PCM_NOIRQ;
4308 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004309 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004310 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004311 } else
4312 flags |= PCM_MONOTONIC;
4313
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004314 if ((adev->vr_audio_mode_enabled) &&
4315 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4316 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4317 "PCM_Dev %d Topology", out->pcm_device_id);
4318 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4319 if (!ctl) {
4320 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4321 __func__, mixer_ctl_name);
4322 } else {
4323 //if success use ULLPP
4324 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4325 __func__, mixer_ctl_name, out->pcm_device_id);
4326 //There is a still a possibility that some sessions
4327 // that request for FAST|RAW when 3D audio is active
4328 //can go through ULLPP. Ideally we expects apps to
4329 //listen to audio focus and stop concurrent playback
4330 //Also, we will look for mode flag (voice_in_communication)
4331 //before enabling the realtime flag.
4332 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4333 }
4334 }
4335
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304336 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4337 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304338
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004339 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4340 flags, pcm_open_retry_count,
4341 &(out->config));
4342 if (out->pcm == NULL) {
4343 ret = -EIO;
4344 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004346
4347 if (is_haptic_usecase) {
4348 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4349 adev->haptic_pcm_device_id,
4350 flags, pcm_open_retry_count,
4351 &(adev->haptics_config));
4352 // failure to open haptics pcm shouldnt stop audio,
4353 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004354
4355 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4356 ALOGD("%s: enable haptic audio synchronization", __func__);
4357 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4358 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004359 }
4360
Zhou Song2b8f28f2017-09-11 10:51:38 +08004361 // apply volume for voip playback after path is set up
4362 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4363 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304364 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4365 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304366 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4367 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004368 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4369 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304370#ifdef SOFT_VOLUME
4371 out_set_soft_volume_params(&out->stream);
4372#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304373 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004374 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004375 /*
4376 * set custom channel map if:
4377 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4378 * 2. custom channel map has been set by client
4379 * else default channel map of FC/FR/FL can always be set to DSP
4380 */
4381 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4382 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004383 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004384 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4385 adev->dsp_bit_width_enforce_mode,
4386 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004388 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004389 out->compr = compress_open(adev->snd_card,
4390 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004391 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004392 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304393 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304394 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4395 adev->card_status = CARD_STATUS_OFFLINE;
4396 out->card_status = CARD_STATUS_OFFLINE;
4397 ret = -EIO;
4398 goto error_open;
4399 }
4400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004401 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004402 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004403 compress_close(out->compr);
4404 out->compr = NULL;
4405 ret = -EIO;
4406 goto error_open;
4407 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304408 /* compress_open sends params of the track, so reset the flag here */
4409 out->is_compr_metadata_avail = false;
4410
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004411 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004412 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004413
Fred Oh3f43e742015-03-04 18:42:34 -08004414 /* Since small bufs uses blocking writes, a write will be blocked
4415 for the default max poll time (20s) in the event of an SSR.
4416 Reduce the poll time to observe and deal with SSR faster.
4417 */
Ashish Jain5106d362016-05-11 19:23:33 +05304418 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004419 compress_set_max_poll_wait(out->compr, 1000);
4420 }
4421
Manish Dewangan69426c82017-01-30 17:35:36 +05304422 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304423 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304424
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004425 audio_extn_dts_create_state_notifier_node(out->usecase);
4426 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4427 popcount(out->channel_mask),
4428 out->playback_started);
4429
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004430#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304431 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004432 audio_extn_dolby_send_ddp_endp_params(adev);
4433#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304434 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4435 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004436 if (adev->visualizer_start_output != NULL)
4437 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4438 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304439 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004440 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004441 }
Derek Chenf13dd492018-11-13 14:53:51 -08004442
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004443 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004444 /* Update cached volume from media to offload/direct stream */
4445 struct listnode *node = NULL;
4446 list_for_each(node, &adev->active_outputs_list) {
4447 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4448 streams_output_ctxt_t,
4449 list);
4450 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4451 out->volume_l = out_ctxt->output->volume_l;
4452 out->volume_r = out_ctxt->output->volume_r;
4453 }
4454 }
4455 out_set_compr_volume(&out->stream,
4456 out->volume_l, out->volume_r);
4457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004459
4460 if (ret == 0) {
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304461 if (out->flags == AUDIO_OUTPUT_FLAG_FAST)
4462 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004463 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004464 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4465 ALOGE("%s: pcm stream not ready", __func__);
4466 goto error_open;
4467 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004468 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004469 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004470 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004471 if (ret < 0)
4472 goto error_open;
4473 }
4474 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004475 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304476 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304477 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004478
vivek mehtad15d2bf2019-05-17 13:35:10 -07004479 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4480 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4481 audio_low_latency_hint_start();
4482 }
4483
Manish Dewangan21a850a2017-08-14 12:03:55 +05304484 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004485 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004486 if (ret < 0)
4487 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4488 }
4489
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004490 // consider a scenario where on pause lower layers are tear down.
4491 // so on resume, swap mixer control need to be sent only when
4492 // backend is active, hence rather than sending from enable device
4493 // sending it from start of streamtream
4494
4495 platform_set_swap_channels(adev, true);
4496
Haynes Mathew George380745d2017-10-04 15:27:45 -07004497 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304498 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004499 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004500error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004501 if (adev->haptic_pcm) {
4502 pcm_close(adev->haptic_pcm);
4503 adev->haptic_pcm = NULL;
4504 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004505 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304506 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004508error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304509 /*
4510 * sleep 50ms to allow sufficient time for kernel
4511 * drivers to recover incases like SSR.
4512 */
4513 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004514error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004515 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304516 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004517 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518}
4519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520static int check_input_parameters(uint32_t sample_rate,
4521 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004522 int channel_count,
4523 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004525 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304527 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4528 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4529 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004530 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004531 !audio_extn_compr_cap_format_supported(format) &&
4532 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004533 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004534
Aalique Grahame22e49102018-12-18 14:23:57 -08004535 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4536 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4537 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4538 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4539 return -EINVAL;
4540 }
4541
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004542 switch (channel_count) {
4543 case 1:
4544 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304545 case 3:
4546 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004547 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004548 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304549 case 10:
4550 case 12:
4551 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004552 break;
4553 default:
4554 ret = -EINVAL;
4555 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556
4557 switch (sample_rate) {
4558 case 8000:
4559 case 11025:
4560 case 12000:
4561 case 16000:
4562 case 22050:
4563 case 24000:
4564 case 32000:
4565 case 44100:
4566 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004567 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304568 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004569 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304570 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 break;
4572 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004573 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574 }
4575
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004576 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577}
4578
Naresh Tanniru04f71882018-06-26 17:46:22 +05304579
4580/** Add a value in a list if not already present.
4581 * @return true if value was successfully inserted or already present,
4582 * false if the list is full and does not contain the value.
4583 */
4584static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4585 for (size_t i = 0; i < list_length; i++) {
4586 if (list[i] == value) return true; // value is already present
4587 if (list[i] == 0) { // no values in this slot
4588 list[i] = value;
4589 return true; // value inserted
4590 }
4591 }
4592 return false; // could not insert value
4593}
4594
4595/** Add channel_mask in supported_channel_masks if not already present.
4596 * @return true if channel_mask was successfully inserted or already present,
4597 * false if supported_channel_masks is full and does not contain channel_mask.
4598 */
4599static void register_channel_mask(audio_channel_mask_t channel_mask,
4600 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4601 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4602 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4603}
4604
4605/** Add format in supported_formats if not already present.
4606 * @return true if format was successfully inserted or already present,
4607 * false if supported_formats is full and does not contain format.
4608 */
4609static void register_format(audio_format_t format,
4610 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4611 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4612 "%s: stream can not declare supporting its format %x", __func__, format);
4613}
4614/** Add sample_rate in supported_sample_rates if not already present.
4615 * @return true if sample_rate was successfully inserted or already present,
4616 * false if supported_sample_rates is full and does not contain sample_rate.
4617 */
4618static void register_sample_rate(uint32_t sample_rate,
4619 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4620 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4621 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4622}
4623
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004624static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4625{
4626 uint32_t high = num1, low = num2, temp = 0;
4627
4628 if (!num1 || !num2)
4629 return 0;
4630
4631 if (num1 < num2) {
4632 high = num2;
4633 low = num1;
4634 }
4635
4636 while (low != 0) {
4637 temp = low;
4638 low = high % low;
4639 high = temp;
4640 }
4641 return (num1 * num2)/high;
4642}
4643
4644static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4645{
4646 uint32_t remainder = 0;
4647
4648 if (!multiplier)
4649 return num;
4650
4651 remainder = num % multiplier;
4652 if (remainder)
4653 num += (multiplier - remainder);
4654
4655 return num;
4656}
4657
Aalique Grahame22e49102018-12-18 14:23:57 -08004658static size_t get_stream_buffer_size(size_t duration_ms,
4659 uint32_t sample_rate,
4660 audio_format_t format,
4661 int channel_count,
4662 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663{
4664 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004665 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666
Aalique Grahame22e49102018-12-18 14:23:57 -08004667 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304668 if (is_low_latency){
4669 switch(sample_rate) {
4670 case 48000:
4671 size = 240;
4672 break;
4673 case 32000:
4674 size = 160;
4675 break;
4676 case 24000:
4677 size = 120;
4678 break;
4679 case 16000:
4680 size = 80;
4681 break;
4682 case 8000:
4683 size = 40;
4684 break;
4685 default:
4686 size = 240;
4687 }
4688 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304689
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004690 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004691 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692
Ralf Herzbd08d632018-09-28 15:50:49 +02004693 /* make sure the size is multiple of 32 bytes and additionally multiple of
4694 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004695 * At 48 kHz mono 16-bit PCM:
4696 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4697 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004698 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004699 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004700 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004701
4702 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703}
4704
Aalique Grahame22e49102018-12-18 14:23:57 -08004705static size_t get_input_buffer_size(uint32_t sample_rate,
4706 audio_format_t format,
4707 int channel_count,
4708 bool is_low_latency)
4709{
4710 /* Don't know if USB HIFI in this context so use true to be conservative */
4711 if (check_input_parameters(sample_rate, format, channel_count,
4712 true /*is_usb_hifi */) != 0)
4713 return 0;
4714
4715 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4716 sample_rate,
4717 format,
4718 channel_count,
4719 is_low_latency);
4720}
4721
Derek Chenf6318be2017-06-12 17:16:24 -04004722size_t get_output_period_size(uint32_t sample_rate,
4723 audio_format_t format,
4724 int channel_count,
4725 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304726{
4727 size_t size = 0;
4728 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4729
4730 if ((duration == 0) || (sample_rate == 0) ||
4731 (bytes_per_sample == 0) || (channel_count == 0)) {
4732 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4733 bytes_per_sample, channel_count);
4734 return -EINVAL;
4735 }
4736
4737 size = (sample_rate *
4738 duration *
4739 bytes_per_sample *
4740 channel_count) / 1000;
4741 /*
4742 * To have same PCM samples for all channels, the buffer size requires to
4743 * be multiple of (number of channels * bytes per sample)
4744 * For writes to succeed, the buffer must be written at address which is multiple of 32
4745 */
4746 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4747
4748 return (size/(channel_count * bytes_per_sample));
4749}
4750
Zhou Song48453a02018-01-10 17:50:59 +08004751static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304752{
4753 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004754 uint64_t written_frames = 0;
4755 uint64_t kernel_frames = 0;
4756 uint64_t dsp_frames = 0;
4757 uint64_t signed_frames = 0;
4758 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304759
4760 /* This adjustment accounts for buffering after app processor.
4761 * It is based on estimated DSP latency per use case, rather than exact.
4762 */
George Gao9ba8a142020-07-23 14:30:03 -07004763 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004764 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304765
Zhou Song48453a02018-01-10 17:50:59 +08004766 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004767 written_frames = out->written /
4768 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4769
Ashish Jain5106d362016-05-11 19:23:33 +05304770 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4771 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4772 * hence only estimate.
4773 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004774 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4775 kernel_frames = kernel_buffer_size /
4776 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304777
Weiyin Jiang4813da12020-05-28 00:37:28 +08004778 if (written_frames >= (kernel_frames + dsp_frames))
4779 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304780
Zhou Song48453a02018-01-10 17:50:59 +08004781 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304782 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004783 if (timestamp != NULL )
4784 *timestamp = out->writeAt;
4785 } else if (timestamp != NULL) {
4786 clock_gettime(CLOCK_MONOTONIC, timestamp);
4787 }
4788 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304789
Weiyin Jiang4813da12020-05-28 00:37:28 +08004790 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4791 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304792
4793 return actual_frames_rendered;
4794}
4795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4797{
4798 struct stream_out *out = (struct stream_out *)stream;
4799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004800 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801}
4802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004803static int out_set_sample_rate(struct audio_stream *stream __unused,
4804 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805{
4806 return -ENOSYS;
4807}
4808
4809static size_t out_get_buffer_size(const struct audio_stream *stream)
4810{
4811 struct stream_out *out = (struct stream_out *)stream;
4812
Varun Balaraje49253e2017-07-06 19:48:56 +05304813 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304814 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304815 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304816 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4817 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4818 else
4819 return out->compr_config.fragment_size;
4820 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004821 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304822 else if (is_offload_usecase(out->usecase) &&
4823 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304824 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004825
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004826 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004827 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828}
4829
4830static uint32_t out_get_channels(const struct audio_stream *stream)
4831{
4832 struct stream_out *out = (struct stream_out *)stream;
4833
4834 return out->channel_mask;
4835}
4836
4837static audio_format_t out_get_format(const struct audio_stream *stream)
4838{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004839 struct stream_out *out = (struct stream_out *)stream;
4840
4841 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842}
4843
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004844static int out_set_format(struct audio_stream *stream __unused,
4845 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846{
4847 return -ENOSYS;
4848}
4849
4850static int out_standby(struct audio_stream *stream)
4851{
4852 struct stream_out *out = (struct stream_out *)stream;
4853 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004854 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004855
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304856 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4857 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004859 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004861 if (adev->adm_deregister_stream)
4862 adev->adm_deregister_stream(adev->adm_data, out->handle);
4863
Weiyin Jiang280ea742020-09-08 20:28:22 +08004864 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004865 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004866 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004867
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004870 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4871 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304872 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004873 pthread_mutex_unlock(&adev->lock);
4874 pthread_mutex_unlock(&out->lock);
4875 ALOGD("VOIP output entered standby");
4876 return 0;
4877 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004878 if (out->pcm) {
4879 pcm_close(out->pcm);
4880 out->pcm = NULL;
4881 }
Meng Wanga09da002020-04-20 12:56:04 +08004882 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4883 if (adev->haptic_pcm) {
4884 pcm_close(adev->haptic_pcm);
4885 adev->haptic_pcm = NULL;
4886 }
4887
4888 if (adev->haptic_buffer != NULL) {
4889 free(adev->haptic_buffer);
4890 adev->haptic_buffer = NULL;
4891 adev->haptic_buffer_size = 0;
4892 }
4893 adev->haptic_pcm_device_id = 0;
4894 }
4895
Haynes Mathew George16081042017-05-31 17:16:49 -07004896 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4897 do_stop = out->playback_started;
4898 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004899
4900 if (out->mmap_shared_memory_fd >= 0) {
4901 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4902 __func__, out->mmap_shared_memory_fd);
4903 close(out->mmap_shared_memory_fd);
4904 out->mmap_shared_memory_fd = -1;
4905 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004906 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004907 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004908 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304909 out->send_next_track_params = false;
4910 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004911 out->gapless_mdata.encoder_delay = 0;
4912 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004913 if (out->compr != NULL) {
4914 compress_close(out->compr);
4915 out->compr = NULL;
4916 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004917 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004918 if (do_stop) {
4919 stop_output_stream(out);
4920 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304921 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004922 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004923 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004924 }
4925 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004926 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927 return 0;
4928}
4929
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304930static int out_on_error(struct audio_stream *stream)
4931{
4932 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004933 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304934
4935 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004936 // always send CMD_ERROR for offload streams, this
4937 // is needed e.g. when SSR happens within compress_open
4938 // since the stream is active, offload_callback_thread is also active.
4939 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4940 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004941 }
4942 pthread_mutex_unlock(&out->lock);
4943
4944 status = out_standby(&out->stream.common);
4945
4946 lock_output_stream(out);
4947 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004948 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304949 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304950
4951 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4952 ALOGD("Setting previous card status if offline");
4953 out->prev_card_status_offline = true;
4954 }
4955
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304956 pthread_mutex_unlock(&out->lock);
4957
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004958 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304959}
4960
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304961/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004962 * standby implementation without locks, assumes that the callee already
4963 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304964 */
4965int out_standby_l(struct audio_stream *stream)
4966{
4967 struct stream_out *out = (struct stream_out *)stream;
4968 struct audio_device *adev = out->dev;
4969
4970 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4971 stream, out->usecase, use_case_table[out->usecase]);
4972
4973 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004974 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304975 if (adev->adm_deregister_stream)
4976 adev->adm_deregister_stream(adev->adm_data, out->handle);
4977
Weiyin Jiang280ea742020-09-08 20:28:22 +08004978 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304979 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004980 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304981
4982 out->standby = true;
4983 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4984 voice_extn_compress_voip_close_output_stream(stream);
4985 out->started = 0;
4986 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004987 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304988 return 0;
4989 } else if (!is_offload_usecase(out->usecase)) {
4990 if (out->pcm) {
4991 pcm_close(out->pcm);
4992 out->pcm = NULL;
4993 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004994 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4995 if (adev->haptic_pcm) {
4996 pcm_close(adev->haptic_pcm);
4997 adev->haptic_pcm = NULL;
4998 }
4999
5000 if (adev->haptic_buffer != NULL) {
5001 free(adev->haptic_buffer);
5002 adev->haptic_buffer = NULL;
5003 adev->haptic_buffer_size = 0;
5004 }
5005 adev->haptic_pcm_device_id = 0;
5006 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305007 } else {
5008 ALOGD("copl(%p):standby", out);
5009 out->send_next_track_params = false;
5010 out->is_compr_metadata_avail = false;
5011 out->gapless_mdata.encoder_delay = 0;
5012 out->gapless_mdata.encoder_padding = 0;
5013 if (out->compr != NULL) {
5014 compress_close(out->compr);
5015 out->compr = NULL;
5016 }
5017 }
5018 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005019 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305020 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005021 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305022 return 0;
5023}
5024
Aalique Grahame22e49102018-12-18 14:23:57 -08005025static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026{
Aalique Grahame22e49102018-12-18 14:23:57 -08005027 struct stream_out *out = (struct stream_out *)stream;
5028
5029 // We try to get the lock for consistency,
5030 // but it isn't necessary for these variables.
5031 // If we're not in standby, we may be blocked on a write.
5032 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5033 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5034 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305035#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005036 char buffer[256]; // for statistics formatting
5037 if (!is_offload_usecase(out->usecase)) {
5038 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5039 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5040 }
5041
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005042 if (out->start_latency_ms.n > 0) {
5043 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5044 dprintf(fd, " Start latency ms: %s\n", buffer);
5045 }
Dechen Chai22768452021-07-30 09:29:16 +05305046#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005047 if (locked) {
5048 pthread_mutex_unlock(&out->lock);
5049 }
5050
Dechen Chai22768452021-07-30 09:29:16 +05305051#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005052 // dump error info
5053 (void)error_log_dump(
5054 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305055#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005056 return 0;
5057}
5058
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005059static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5060{
5061 int ret = 0;
5062 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005063
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005064 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005065 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005066 return -EINVAL;
5067 }
5068
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305069 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005070
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005071 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5072 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305073 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005074 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005075 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5076 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305077 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005078 }
5079
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005080 ALOGV("%s new encoder delay %u and padding %u", __func__,
5081 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5082
5083 return 0;
5084}
5085
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005086static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5087{
5088 return out == adev->primary_output || out == adev->voice_tx_output;
5089}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005090
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305091// note: this call is safe only if the stream_cb is
5092// removed first in close_output_stream (as is done now).
5093static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5094{
5095 if (!stream || !parms)
5096 return;
5097
5098 struct stream_out *out = (struct stream_out *)stream;
5099 struct audio_device *adev = out->dev;
5100
5101 card_status_t status;
5102 int card;
5103 if (parse_snd_card_status(parms, &card, &status) < 0)
5104 return;
5105
5106 pthread_mutex_lock(&adev->lock);
5107 bool valid_cb = (card == adev->snd_card);
5108 pthread_mutex_unlock(&adev->lock);
5109
5110 if (!valid_cb)
5111 return;
5112
5113 lock_output_stream(out);
5114 if (out->card_status != status)
5115 out->card_status = status;
5116 pthread_mutex_unlock(&out->lock);
5117
5118 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5119 use_case_table[out->usecase],
5120 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5121
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305122 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305123 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305124 if (voice_is_call_state_active(adev) &&
5125 out == adev->primary_output) {
5126 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5127 pthread_mutex_lock(&adev->lock);
5128 voice_stop_call(adev);
5129 adev->mode = AUDIO_MODE_NORMAL;
5130 pthread_mutex_unlock(&adev->lock);
5131 }
5132 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305133 return;
5134}
5135
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005136int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005137 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005138{
5139 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005140 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005141 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005142 bool bypass_a2dp = false;
5143 bool reconfig = false;
5144 unsigned long service_interval = 0;
5145
5146 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005147 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5148
5149 list_init(&new_devices);
5150 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005151
5152 lock_output_stream(out);
5153 pthread_mutex_lock(&adev->lock);
5154
5155 /*
5156 * When HDMI cable is unplugged the music playback is paused and
5157 * the policy manager sends routing=0. But the audioflinger continues
5158 * to write data until standby time (3sec). As the HDMI core is
5159 * turned off, the write gets blocked.
5160 * Avoid this by routing audio to speaker until standby.
5161 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005162 if (is_single_device_type_equal(&out->device_list,
5163 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005164 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005165 !audio_extn_passthru_is_passthrough_stream(out) &&
5166 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005167 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005168 }
5169 /*
5170 * When A2DP is disconnected the
5171 * music playback is paused and the policy manager sends routing=0
5172 * But the audioflinger continues to write data until standby time
5173 * (3sec). As BT is turned off, the write gets blocked.
5174 * Avoid this by routing audio to speaker until standby.
5175 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005176 if (is_a2dp_out_device_type(&out->device_list) &&
5177 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005178 !audio_extn_a2dp_source_is_ready() &&
5179 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005180 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005181 }
5182 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005183 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005184 * and the policy manager send routing=0. But if the USB is connected
5185 * back before the standby time, AFE is not closed and opened
5186 * when USB is connected back. So routing to speker will guarantee
5187 * AFE reconfiguration and AFE will be opend once USB is connected again
5188 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005189 if (is_usb_out_device_type(&out->device_list) &&
5190 list_empty(&new_devices) &&
5191 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305192 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5193 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5194 else
5195 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005196 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005197 /* To avoid a2dp to sco overlapping / BT device improper state
5198 * check with BT lib about a2dp streaming support before routing
5199 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005200 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005201 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005202 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5203 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005204 //combo usecase just by pass a2dp
5205 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5206 bypass_a2dp = true;
5207 } else {
5208 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5209 /* update device to a2dp and don't route as BT returned error
5210 * However it is still possible a2dp routing called because
5211 * of current active device disconnection (like wired headset)
5212 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005213 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005214 pthread_mutex_unlock(&adev->lock);
5215 pthread_mutex_unlock(&out->lock);
5216 goto error;
5217 }
5218 }
5219 }
5220
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005221 // Workaround: If routing to an non existing usb device, fail gracefully
5222 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005223 if (is_usb_out_device_type(&new_devices)) {
5224 struct str_parms *parms =
5225 str_parms_create_str(get_usb_device_address(&new_devices));
5226 if (!parms)
5227 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005228 if (!audio_extn_usb_connected(NULL)) {
5229 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005230 pthread_mutex_unlock(&adev->lock);
5231 pthread_mutex_unlock(&out->lock);
5232 str_parms_destroy(parms);
5233 ret = -ENOSYS;
5234 goto error;
5235 }
5236 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005237 }
5238
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005239 // Workaround: If routing to an non existing hdmi device, fail gracefully
5240 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5241 (platform_get_edid_info_v2(adev->platform,
5242 out->extconn.cs.controller,
5243 out->extconn.cs.stream) != 0)) {
5244 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5245 pthread_mutex_unlock(&adev->lock);
5246 pthread_mutex_unlock(&out->lock);
5247 ret = -ENOSYS;
5248 goto error;
5249 }
5250
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005251 /*
5252 * select_devices() call below switches all the usecases on the same
5253 * backend to the new device. Refer to check_usecases_codec_backend() in
5254 * the select_devices(). But how do we undo this?
5255 *
5256 * For example, music playback is active on headset (deep-buffer usecase)
5257 * and if we go to ringtones and select a ringtone, low-latency usecase
5258 * will be started on headset+speaker. As we can't enable headset+speaker
5259 * and headset devices at the same time, select_devices() switches the music
5260 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5261 * So when the ringtone playback is completed, how do we undo the same?
5262 *
5263 * We are relying on the out_set_parameters() call on deep-buffer output,
5264 * once the ringtone playback is ended.
5265 * NOTE: We should not check if the current devices are same as new devices.
5266 * Because select_devices() must be called to switch back the music
5267 * playback to headset.
5268 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005269 if (!list_empty(&new_devices)) {
5270 bool same_dev = compare_devices(&out->device_list, &new_devices);
5271 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005272
5273 if (output_drives_call(adev, out)) {
5274 if (!voice_is_call_state_active(adev)) {
5275 if (adev->mode == AUDIO_MODE_IN_CALL) {
5276 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005277 ret = voice_start_call(adev);
5278 }
5279 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005280 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005281 adev->current_call_output = out;
5282 voice_update_devices_for_all_voice_usecases(adev);
5283 }
5284 }
5285
Mingshu Pang971ff702020-09-09 15:28:22 +08005286 if (is_usb_out_device_type(&out->device_list)) {
5287 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5288 audio_extn_usb_set_service_interval(true /*playback*/,
5289 service_interval,
5290 &reconfig);
5291 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5292 }
5293
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005294 if (!out->standby) {
5295 if (!same_dev) {
5296 ALOGV("update routing change");
5297 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5298 adev->perf_lock_opts,
5299 adev->perf_lock_opts_size);
5300 if (adev->adm_on_routing_change)
5301 adev->adm_on_routing_change(adev->adm_data,
5302 out->handle);
5303 }
5304 if (!bypass_a2dp) {
5305 select_devices(adev, out->usecase);
5306 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005307 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5308 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005309 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005310 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005311 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005312 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005313 }
5314
5315 if (!same_dev) {
5316 // on device switch force swap, lower functions will make sure
5317 // to check if swap is allowed or not.
5318 platform_set_swap_channels(adev, true);
5319 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5320 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005321 pthread_mutex_lock(&out->latch_lock);
5322 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5323 if (out->a2dp_muted) {
5324 out->a2dp_muted = false;
5325 if (is_offload_usecase(out->usecase))
5326 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5327 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5328 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005329 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005330 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005331 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5332 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5333 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005334 }
5335 }
5336
5337 pthread_mutex_unlock(&adev->lock);
5338 pthread_mutex_unlock(&out->lock);
5339
5340 /*handles device and call state changes*/
5341 audio_extn_extspk_update(adev->extspk);
5342
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005343 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005344error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005345 ALOGV("%s: exit: code(%d)", __func__, ret);
5346 return ret;
5347}
5348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5350{
5351 struct stream_out *out = (struct stream_out *)stream;
5352 struct audio_device *adev = out->dev;
5353 struct str_parms *parms;
5354 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005355 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005356 int ext_controller = -1;
5357 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358
sangwoobc677242013-08-08 16:53:43 +09005359 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005360 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005361 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305362 if (!parms)
5363 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005364
5365 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5366 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005367 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005368 out->extconn.cs.controller = ext_controller;
5369 out->extconn.cs.stream = ext_stream;
5370 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5371 use_case_table[out->usecase], out->extconn.cs.controller,
5372 out->extconn.cs.stream);
5373 }
5374
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005375 if (out == adev->primary_output) {
5376 pthread_mutex_lock(&adev->lock);
5377 audio_extn_set_parameters(adev, parms);
5378 pthread_mutex_unlock(&adev->lock);
5379 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005380 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005381 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005382 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005383
5384 audio_extn_dts_create_state_notifier_node(out->usecase);
5385 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5386 popcount(out->channel_mask),
5387 out->playback_started);
5388
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005389 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005390 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005391
Surendar Karkaf51b5842018-04-26 11:28:38 +05305392 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5393 sizeof(value));
5394 if (err >= 0) {
5395 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5396 audio_extn_send_dual_mono_mixing_coefficients(out);
5397 }
5398
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305399 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5400 if (err >= 0) {
5401 strlcpy(out->profile, value, sizeof(out->profile));
5402 ALOGV("updating stream profile with value '%s'", out->profile);
5403 lock_output_stream(out);
5404 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5405 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005406 &out->device_list, out->flags,
5407 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305408 out->sample_rate, out->bit_width,
5409 out->channel_mask, out->profile,
5410 &out->app_type_cfg);
5411 pthread_mutex_unlock(&out->lock);
5412 }
5413
Alexy Joseph98988832017-01-13 14:56:59 -08005414 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005415 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5416 // and vendor.audio.hal.output.suspend.supported is set to true
5417 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005418 //check suspend parameter only for low latency and if the property
5419 //is enabled
5420 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5421 ALOGI("%s: got suspend_playback %s", __func__, value);
5422 lock_output_stream(out);
5423 if (!strncmp(value, "false", 5)) {
5424 //suspend_playback=false is supposed to set QOS value back to 75%
5425 //the mixer control sent with value Enable will achieve that
5426 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5427 } else if (!strncmp (value, "true", 4)) {
5428 //suspend_playback=true is supposed to remove QOS value
5429 //resetting the mixer control will set the default value
5430 //for the mixer control which is Disable and this removes the QOS vote
5431 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5432 } else {
5433 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5434 " got %s", __func__, value);
5435 ret = -1;
5436 }
5437
5438 if (ret != 0) {
5439 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5440 __func__, out->pm_qos_mixer_path, ret);
5441 }
5442
5443 pthread_mutex_unlock(&out->lock);
5444 }
5445 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005446
Alexy Joseph98988832017-01-13 14:56:59 -08005447 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005448 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305449error:
Eric Laurent994a6932013-07-17 11:51:42 -07005450 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 return ret;
5452}
5453
Paul McLeana50b7332018-12-17 08:24:21 -07005454static int in_set_microphone_direction(const struct audio_stream_in *stream,
5455 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005456 struct stream_in *in = (struct stream_in *)stream;
5457
5458 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5459
5460 in->direction = dir;
5461
5462 if (in->standby)
5463 return 0;
5464
5465 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005466}
5467
5468static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005469 struct stream_in *in = (struct stream_in *)stream;
5470
5471 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5472
5473 if (zoom > 1.0 || zoom < -1.0)
5474 return -EINVAL;
5475
5476 in->zoom = zoom;
5477
5478 if (in->standby)
5479 return 0;
5480
5481 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005482}
5483
5484
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005485static bool stream_get_parameter_channels(struct str_parms *query,
5486 struct str_parms *reply,
5487 audio_channel_mask_t *supported_channel_masks) {
5488 int ret = -1;
5489 char value[512];
5490 bool first = true;
5491 size_t i, j;
5492
5493 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5494 ret = 0;
5495 value[0] = '\0';
5496 i = 0;
5497 while (supported_channel_masks[i] != 0) {
5498 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5499 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5500 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305501 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005502
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305503 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005504 first = false;
5505 break;
5506 }
5507 }
5508 i++;
5509 }
5510 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5511 }
5512 return ret == 0;
5513}
5514
5515static bool stream_get_parameter_formats(struct str_parms *query,
5516 struct str_parms *reply,
5517 audio_format_t *supported_formats) {
5518 int ret = -1;
5519 char value[256];
5520 size_t i, j;
5521 bool first = true;
5522
5523 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5524 ret = 0;
5525 value[0] = '\0';
5526 i = 0;
5527 while (supported_formats[i] != 0) {
5528 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5529 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5530 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305531 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005532 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305533 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005534 first = false;
5535 break;
5536 }
5537 }
5538 i++;
5539 }
5540 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5541 }
5542 return ret == 0;
5543}
5544
5545static bool stream_get_parameter_rates(struct str_parms *query,
5546 struct str_parms *reply,
5547 uint32_t *supported_sample_rates) {
5548
5549 int i;
5550 char value[256];
5551 int ret = -1;
5552 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5553 ret = 0;
5554 value[0] = '\0';
5555 i=0;
5556 int cursor = 0;
5557 while (supported_sample_rates[i]) {
5558 int avail = sizeof(value) - cursor;
5559 ret = snprintf(value + cursor, avail, "%s%d",
5560 cursor > 0 ? "|" : "",
5561 supported_sample_rates[i]);
5562 if (ret < 0 || ret >= avail) {
5563 // if cursor is at the last element of the array
5564 // overwrite with \0 is duplicate work as
5565 // snprintf already put a \0 in place.
5566 // else
5567 // we had space to write the '|' at value[cursor]
5568 // (which will be overwritten) or no space to fill
5569 // the first element (=> cursor == 0)
5570 value[cursor] = '\0';
5571 break;
5572 }
5573 cursor += ret;
5574 ++i;
5575 }
5576 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5577 value);
5578 }
5579 return ret >= 0;
5580}
5581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005582static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5583{
5584 struct stream_out *out = (struct stream_out *)stream;
5585 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005586 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005587 char value[256];
5588 struct str_parms *reply = str_parms_create();
5589 size_t i, j;
5590 int ret;
5591 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005592
5593 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005594 if (reply) {
5595 str_parms_destroy(reply);
5596 }
5597 if (query) {
5598 str_parms_destroy(query);
5599 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005600 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5601 return NULL;
5602 }
5603
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005604 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5606 if (ret >= 0) {
5607 value[0] = '\0';
5608 i = 0;
5609 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005610 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5611 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005612 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005613 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005615 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005616 first = false;
5617 break;
5618 }
5619 }
5620 i++;
5621 }
5622 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5623 str = str_parms_to_str(reply);
5624 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005625 voice_extn_out_get_parameters(out, query, reply);
5626 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005627 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005628
Alexy Joseph62142aa2015-11-16 15:10:34 -08005629
5630 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5631 if (ret >= 0) {
5632 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305633 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5634 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005635 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305636 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005637 } else {
5638 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305639 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005640 }
5641 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005642 if (str)
5643 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005644 str = str_parms_to_str(reply);
5645 }
5646
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005647 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5648 if (ret >= 0) {
5649 value[0] = '\0';
5650 i = 0;
5651 first = true;
5652 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005653 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5654 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005655 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005656 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005657 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005658 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005659 first = false;
5660 break;
5661 }
5662 }
5663 i++;
5664 }
5665 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005666 if (str)
5667 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005668 str = str_parms_to_str(reply);
5669 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005670
5671 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5672 if (ret >= 0) {
5673 value[0] = '\0';
5674 i = 0;
5675 first = true;
5676 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005677 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5678 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005679 if (!first) {
5680 strlcat(value, "|", sizeof(value));
5681 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005682 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005683 first = false;
5684 break;
5685 }
5686 }
5687 i++;
5688 }
5689 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5690 if (str)
5691 free(str);
5692 str = str_parms_to_str(reply);
5693 }
5694
Alexy Joseph98988832017-01-13 14:56:59 -08005695 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5696 //only low latency track supports suspend_resume
5697 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005698 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005699 if (str)
5700 free(str);
5701 str = str_parms_to_str(reply);
5702 }
5703
5704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705 str_parms_destroy(query);
5706 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005707 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 return str;
5709}
5710
5711static uint32_t out_get_latency(const struct audio_stream_out *stream)
5712{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005713 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005714 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005715 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005716
Alexy Josephaa54c872014-12-03 02:46:47 -08005717 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305718 lock_output_stream(out);
5719 latency = audio_extn_utils_compress_get_dsp_latency(out);
5720 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005721 } else if ((out->realtime) ||
5722 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005723 // since the buffer won't be filled up faster than realtime,
5724 // return a smaller number
5725 if (out->config.rate)
5726 period_ms = (out->af_period_multiplier * out->config.period_size *
5727 1000) / (out->config.rate);
5728 else
5729 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005730 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005731 } else {
5732 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005733 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305734 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5735 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005736 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005737 }
5738
Zhou Songd2537a02020-06-11 22:04:46 +08005739 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005740 latency += audio_extn_a2dp_get_encoder_latency();
5741
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305742 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005743 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005744}
5745
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305746static float AmpToDb(float amplification)
5747{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305748 float db = DSD_VOLUME_MIN_DB;
5749 if (amplification > 0) {
5750 db = 20 * log10(amplification);
5751 if(db < DSD_VOLUME_MIN_DB)
5752 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305753 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305754 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305755}
5756
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305757#ifdef SOFT_VOLUME
5758static int out_set_soft_volume_params(struct audio_stream_out *stream)
5759{
5760 struct stream_out *out = (struct stream_out *)stream;
5761 int ret = 0;
5762 char mixer_ctl_name[128];
5763 struct audio_device *adev = out->dev;
5764 struct mixer_ctl *ctl = NULL;
5765 struct soft_step_volume_params *volume_params = NULL;
5766
5767 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5768 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5769 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5770 if (!ctl) {
5771 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5772 return -EINVAL;
5773 }
5774
5775 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5776 if (volume_params == NULL){
5777 ALOGE("%s : malloc is failed for volume params", __func__);
5778 return -EINVAL;
5779 } else {
5780 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5781 if (ret < 0) {
5782 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305783 ret = -EINVAL;
5784 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305785 }
5786
5787 }
5788 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5789 if (ret < 0) {
5790 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305791 ret = -EINVAL;
5792 goto ERR_EXIT;
5793 }
5794
5795 if (volume_params) {
5796 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305797 }
5798 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305799
5800ERR_EXIT:
5801 if (volume_params) {
5802 free(volume_params);
5803 }
5804 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305805}
5806#endif
5807
Arun Mirpuri5d170872019-03-26 13:21:31 -07005808static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5809 float right)
5810{
5811 struct stream_out *out = (struct stream_out *)stream;
5812 long volume = 0;
5813 char mixer_ctl_name[128] = "";
5814 struct audio_device *adev = out->dev;
5815 struct mixer_ctl *ctl = NULL;
5816 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5817 PCM_PLAYBACK);
5818
5819 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5820 "Playback %d Volume", pcm_device_id);
5821 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5822 if (!ctl) {
5823 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5824 __func__, mixer_ctl_name);
5825 return -EINVAL;
5826 }
5827 if (left != right)
5828 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5829 __func__, left, right);
5830 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5831 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5832 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5833 __func__, mixer_ctl_name, volume);
5834 return -EINVAL;
5835 }
5836 return 0;
5837}
5838
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305839static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5840 float right)
5841{
5842 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305843 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305844 char mixer_ctl_name[128];
5845 struct audio_device *adev = out->dev;
5846 struct mixer_ctl *ctl;
5847 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5848 PCM_PLAYBACK);
5849
5850 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5851 "Compress Playback %d Volume", pcm_device_id);
5852 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5853 if (!ctl) {
5854 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5855 __func__, mixer_ctl_name);
5856 return -EINVAL;
5857 }
5858 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5859 __func__, mixer_ctl_name, left, right);
5860 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5861 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5862 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5863
5864 return 0;
5865}
5866
Zhou Song2b8f28f2017-09-11 10:51:38 +08005867static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5868 float right)
5869{
5870 struct stream_out *out = (struct stream_out *)stream;
5871 char mixer_ctl_name[] = "App Type Gain";
5872 struct audio_device *adev = out->dev;
5873 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305874 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005875
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005876 if (!is_valid_volume(left, right)) {
5877 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5878 __func__, left, right);
5879 return -EINVAL;
5880 }
5881
Zhou Song2b8f28f2017-09-11 10:51:38 +08005882 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5883 if (!ctl) {
5884 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5885 __func__, mixer_ctl_name);
5886 return -EINVAL;
5887 }
5888
5889 set_values[0] = 0; //0: Rx Session 1:Tx Session
5890 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305891 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5892 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005893
5894 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5895 return 0;
5896}
5897
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305898static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5899 float right)
5900{
5901 struct stream_out *out = (struct stream_out *)stream;
5902 /* Volume control for pcm playback */
5903 if (left != right) {
5904 return -EINVAL;
5905 } else {
5906 char mixer_ctl_name[128];
5907 struct audio_device *adev = out->dev;
5908 struct mixer_ctl *ctl;
5909 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5910 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5911 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5912 if (!ctl) {
5913 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5914 return -EINVAL;
5915 }
5916
5917 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5918 int ret = mixer_ctl_set_value(ctl, 0, volume);
5919 if (ret < 0) {
5920 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5921 return -EINVAL;
5922 }
5923
5924 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5925
5926 return 0;
5927 }
5928}
5929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005930static int out_set_volume(struct audio_stream_out *stream, float left,
5931 float right)
5932{
Eric Laurenta9024de2013-04-04 09:19:12 -07005933 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005934 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305935 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005936
Arun Mirpuri5d170872019-03-26 13:21:31 -07005937 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005938 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5939 /* only take left channel into account: the API is for stereo anyway */
5940 out->muted = (left == 0.0f);
5941 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005942 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305943 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005944 /*
5945 * Set mute or umute on HDMI passthrough stream.
5946 * Only take left channel into account.
5947 * Mute is 0 and unmute 1
5948 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305949 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305950 } else if (out->format == AUDIO_FORMAT_DSD){
5951 char mixer_ctl_name[128] = "DSD Volume";
5952 struct audio_device *adev = out->dev;
5953 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5954
5955 if (!ctl) {
5956 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5957 __func__, mixer_ctl_name);
5958 return -EINVAL;
5959 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305960 volume[0] = (long)(AmpToDb(left));
5961 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305962 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5963 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005964 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005965 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005966 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5967 struct listnode *node = NULL;
5968 list_for_each(node, &adev->active_outputs_list) {
5969 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5970 streams_output_ctxt_t,
5971 list);
5972 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5973 out->volume_l = out_ctxt->output->volume_l;
5974 out->volume_r = out_ctxt->output->volume_r;
5975 }
5976 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005977 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005978 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005979 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5980 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005981 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005982 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005983 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005984 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005985 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5986 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305987 ret = out_set_compr_volume(stream, left, right);
5988 out->volume_l = left;
5989 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005990 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305991 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005992 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005993 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005994 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5995 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005996 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005997 if (!out->standby) {
5998 audio_extn_utils_send_app_type_gain(out->dev,
5999 out->app_type_cfg.app_type,
6000 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006001 if (!out->a2dp_muted)
6002 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006003 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006004 out->volume_l = left;
6005 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006006 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006007 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006008 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6009 ALOGV("%s: MMAP set volume called", __func__);
6010 if (!out->standby)
6011 ret = out_set_mmap_volume(stream, left, right);
6012 out->volume_l = left;
6013 out->volume_r = right;
6014 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306015 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306016 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6017 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006018 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306019 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006020 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306021 ret = out_set_pcm_volume(stream, left, right);
6022 else
6023 out->apply_volume = true;
6024
6025 out->volume_l = left;
6026 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006027 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306028 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006029 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6030 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006031 pthread_mutex_lock(&out->latch_lock);
6032 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006033 ret = out_set_pcm_volume(stream, left, right);
6034 out->volume_l = left;
6035 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006036 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006037 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006038 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040 return -ENOSYS;
6041}
6042
Zhou Songc9672822017-08-16 16:01:39 +08006043static void update_frames_written(struct stream_out *out, size_t bytes)
6044{
6045 size_t bpf = 0;
6046
6047 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6048 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6049 bpf = 1;
6050 else if (!is_offload_usecase(out->usecase))
6051 bpf = audio_bytes_per_sample(out->format) *
6052 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006053
6054 pthread_mutex_lock(&out->position_query_lock);
6055 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006056 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006057 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6058 }
6059 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006060}
6061
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006062int split_and_write_audio_haptic_data(struct stream_out *out,
6063 const void *buffer, size_t bytes_to_write)
6064{
6065 struct audio_device *adev = out->dev;
6066
6067 int ret = 0;
6068 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6069 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6070 size_t frame_size = channel_count * bytes_per_sample;
6071 size_t frame_count = bytes_to_write / frame_size;
6072
6073 bool force_haptic_path =
6074 property_get_bool("vendor.audio.test_haptic", false);
6075
6076 // extract Haptics data from Audio buffer
6077 bool alloc_haptic_buffer = false;
6078 int haptic_channel_count = adev->haptics_config.channels;
6079 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6080 size_t audio_frame_size = frame_size - haptic_frame_size;
6081 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6082
6083 if (adev->haptic_buffer == NULL) {
6084 alloc_haptic_buffer = true;
6085 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6086 free(adev->haptic_buffer);
6087 adev->haptic_buffer_size = 0;
6088 alloc_haptic_buffer = true;
6089 }
6090
6091 if (alloc_haptic_buffer) {
6092 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006093 if(adev->haptic_buffer == NULL) {
6094 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6095 return -ENOMEM;
6096 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006097 adev->haptic_buffer_size = total_haptic_buffer_size;
6098 }
6099
6100 size_t src_index = 0, aud_index = 0, hap_index = 0;
6101 uint8_t *audio_buffer = (uint8_t *)buffer;
6102 uint8_t *haptic_buffer = adev->haptic_buffer;
6103
6104 // This is required for testing only. This works for stereo data only.
6105 // One channel is fed to audio stream and other to haptic stream for testing.
6106 if (force_haptic_path)
6107 audio_frame_size = haptic_frame_size = bytes_per_sample;
6108
6109 for (size_t i = 0; i < frame_count; i++) {
6110 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6111 audio_frame_size);
6112 aud_index += audio_frame_size;
6113 src_index += audio_frame_size;
6114
6115 if (adev->haptic_pcm)
6116 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6117 haptic_frame_size);
6118 hap_index += haptic_frame_size;
6119 src_index += haptic_frame_size;
6120
6121 // This is required for testing only.
6122 // Discard haptic channel data.
6123 if (force_haptic_path)
6124 src_index += haptic_frame_size;
6125 }
6126
6127 // write to audio pipeline
6128 ret = pcm_write(out->pcm, (void *)audio_buffer,
6129 frame_count * audio_frame_size);
6130
6131 // write to haptics pipeline
6132 if (adev->haptic_pcm)
6133 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6134 frame_count * haptic_frame_size);
6135
6136 return ret;
6137}
6138
Aalique Grahame22e49102018-12-18 14:23:57 -08006139#ifdef NO_AUDIO_OUT
6140static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6141 const void *buffer __unused, size_t bytes)
6142{
6143 struct stream_out *out = (struct stream_out *)stream;
6144
6145 /* No Output device supported other than BT for playback.
6146 * Sleep for the amount of buffer duration
6147 */
6148 lock_output_stream(out);
6149 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6150 (const struct audio_stream_out *)&out->stream) /
6151 out_get_sample_rate(&out->stream.common));
6152 pthread_mutex_unlock(&out->lock);
6153 return bytes;
6154}
6155#endif
6156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006157static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6158 size_t bytes)
6159{
6160 struct stream_out *out = (struct stream_out *)stream;
6161 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006162 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306163 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006164 const size_t frame_size = audio_stream_out_frame_size(stream);
6165 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306166 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006167 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006168
Haynes Mathew George380745d2017-10-04 15:27:45 -07006169 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006170 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306171
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006172 if (CARD_STATUS_OFFLINE == out->card_status ||
6173 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006174
Dhananjay Kumarac341582017-02-23 23:42:25 +05306175 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306176 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306177 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6178 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006179 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306180 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306181 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306182 ALOGD(" %s: sound card is not active/SSR state", __func__);
6183 ret= -EIO;
6184 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306185 }
6186 }
6187
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306188 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306189 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306190 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306191 goto exit;
6192 }
6193
Haynes Mathew George16081042017-05-31 17:16:49 -07006194 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6195 ret = -EINVAL;
6196 goto exit;
6197 }
6198
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006199 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306200 !out->is_iec61937_info_available) {
6201
6202 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6203 out->is_iec61937_info_available = true;
6204 } else if (audio_extn_passthru_is_enabled()) {
6205 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306206 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306207
6208 if((out->format == AUDIO_FORMAT_DTS) ||
6209 (out->format == AUDIO_FORMAT_DTS_HD)) {
6210 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6211 buffer, bytes);
6212 if (ret) {
6213 if (ret != -ENOSYS) {
6214 out->is_iec61937_info_available = false;
6215 ALOGD("iec61937 transmission info not yet updated retry");
6216 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306217 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306218 /* if stream has started and after that there is
6219 * stream config change (iec transmission config)
6220 * then trigger select_device to update backend configuration.
6221 */
6222 out->stream_config_changed = true;
6223 pthread_mutex_lock(&adev->lock);
6224 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306225 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006226 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306227 ret = -EINVAL;
6228 goto exit;
6229 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306230 pthread_mutex_unlock(&adev->lock);
6231 out->stream_config_changed = false;
6232 out->is_iec61937_info_available = true;
6233 }
6234 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306235
Meng Wang4c32fb42020-01-16 17:57:11 +08006236#ifdef AUDIO_GKI_ENABLED
6237 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6238 compr_passthr = out->compr_config.codec->reserved[0];
6239#else
6240 compr_passthr = out->compr_config.codec->compr_passthr;
6241#endif
6242
Garmond Leung317cbf12017-09-13 16:20:50 -07006243 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006244 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306245 (out->is_iec61937_info_available == true)) {
6246 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6247 ret = -EINVAL;
6248 goto exit;
6249 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306250 }
6251 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306252
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006253 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006254 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006255 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6256 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006257 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306258 ret = -EIO;
6259 goto exit;
6260 }
6261 }
6262 }
6263
Weiyin Jiangabedea32020-12-09 12:49:19 +08006264 if (is_usb_out_device_type(&out->device_list) &&
6265 !audio_extn_usb_connected(NULL)) {
6266 ret = -EIO;
6267 goto exit;
6268 }
6269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006270 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006271 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006272 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6273
Eric Laurent150dbfe2013-02-27 14:31:02 -08006274 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006275 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6276 ret = voice_extn_compress_voip_start_output_stream(out);
6277 else
6278 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006279 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006280 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006281 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006282 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006283 goto exit;
6284 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306285 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006286 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006287
6288 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006289 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006290 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306291 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006292 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006293 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306294
6295 if ((out->is_iec61937_info_available == true) &&
6296 (audio_extn_passthru_is_passthrough_stream(out))&&
6297 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6298 ret = -EINVAL;
6299 goto exit;
6300 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306301 if (out->set_dual_mono)
6302 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006303
Dechen Chai22768452021-07-30 09:29:16 +05306304#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006305 // log startup time in ms.
6306 simple_stats_log(
6307 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306308#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006309 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006310
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006311 if (adev->is_channel_status_set == false &&
6312 compare_device_type(&out->device_list,
6313 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006314 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306315 adev->is_channel_status_set = true;
6316 }
6317
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306318 if ((adev->use_old_pspd_mix_ctrl == true) &&
6319 (out->pspd_coeff_sent == false)) {
6320 /*
6321 * Need to resend pspd coefficients after stream started for
6322 * older kernel version as it does not save the coefficients
6323 * and also stream has to be started for coeff to apply.
6324 */
6325 usecase = get_usecase_from_list(adev, out->usecase);
6326 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306327 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306328 out->pspd_coeff_sent = true;
6329 }
6330 }
6331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006332 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006333 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006334 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006335 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006336 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6337 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306338 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6339 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006340 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306341 out->send_next_track_params = false;
6342 out->is_compr_metadata_avail = false;
6343 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006344 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306345 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306346 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006347
Ashish Jain83a6cc22016-06-28 14:34:17 +05306348 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306349 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306350 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306351 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006352 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306353 return -EINVAL;
6354 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306355 audio_format_t dst_format = out->hal_op_format;
6356 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306357
Dieter Luecking5d57def2018-09-07 14:23:37 +02006358 /* prevent division-by-zero */
6359 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6360 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6361 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6362 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306363 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006364 ATRACE_END();
6365 return -EINVAL;
6366 }
6367
Ashish Jainf1eaa582016-05-23 20:54:24 +05306368 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6369 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6370
Ashish Jain83a6cc22016-06-28 14:34:17 +05306371 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306372 dst_format,
6373 buffer,
6374 src_format,
6375 frames);
6376
Ashish Jain83a6cc22016-06-28 14:34:17 +05306377 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306378 bytes_to_write);
6379
6380 /*Convert written bytes in audio flinger format*/
6381 if (ret > 0)
6382 ret = ((ret * format_to_bitwidth_table[out->format]) /
6383 format_to_bitwidth_table[dst_format]);
6384 }
6385 } else
6386 ret = compress_write(out->compr, buffer, bytes);
6387
Zhou Songc9672822017-08-16 16:01:39 +08006388 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6389 update_frames_written(out, bytes);
6390
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306391 if (ret < 0)
6392 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006393 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306394 /*msg to cb thread only if non blocking write is enabled*/
6395 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306396 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006397 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306398 } else if (-ENETRESET == ret) {
6399 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306400 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306401 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306402 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006403 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306404 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006405 }
Ashish Jain5106d362016-05-11 19:23:33 +05306406
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306407 /* Call compr start only when non-zero bytes of data is there to be rendered */
6408 if (!out->playback_started && ret > 0) {
6409 int status = compress_start(out->compr);
6410 if (status < 0) {
6411 ret = status;
6412 ALOGE("%s: compr start failed with err %d", __func__, errno);
6413 goto exit;
6414 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006415 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006416 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006417 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006418 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006419 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006420
6421 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6422 popcount(out->channel_mask),
6423 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006424 }
6425 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006426 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006427 return ret;
6428 } else {
6429 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006430 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006431 if (out->muted)
6432 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006433 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6434 __func__, frames, frame_size, bytes_to_write);
6435
Aalique Grahame22e49102018-12-18 14:23:57 -08006436 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006437 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6438 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6439 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006440 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6441 int16_t *src = (int16_t *)buffer;
6442 int16_t *dst = (int16_t *)buffer;
6443
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006444 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006445 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006446 "out_write called for %s use case with wrong properties",
6447 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006448
6449 /*
6450 * FIXME: this can be removed once audio flinger mixer supports
6451 * mono output
6452 */
6453
6454 /*
6455 * Code below goes over each frame in the buffer and adds both
6456 * L and R samples and then divides by 2 to convert to mono
6457 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006458 if (channel_count == 2) {
6459 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6460 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6461 }
6462 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006463 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006464 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006465
6466 // Note: since out_get_presentation_position() is called alternating with out_write()
6467 // by AudioFlinger, we can check underruns using the prior timestamp read.
6468 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6469 if (out->last_fifo_valid) {
6470 // compute drain to see if there is an underrun.
6471 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306472 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6473 int64_t frames_by_time =
6474 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6475 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006476 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6477
6478 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306479#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006480 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306481#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006482
6483 ALOGW("%s: underrun(%lld) "
6484 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6485 __func__,
6486 (long long)out->fifo_underruns.n,
6487 (long long)frames_by_time,
6488 (long long)out->last_fifo_frames_remaining);
6489 }
6490 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6491 }
6492
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306493 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006494
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006495 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006496
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006497 if (out->config.rate)
6498 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6499 out->config.rate;
6500
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006501 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006502 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6503
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006504 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006505 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006506 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306507 out->convert_buffer != NULL) {
6508
6509 memcpy_by_audio_format(out->convert_buffer,
6510 out->hal_op_format,
6511 buffer,
6512 out->hal_ip_format,
6513 out->config.period_size * out->config.channels);
6514
6515 ret = pcm_write(out->pcm, out->convert_buffer,
6516 (out->config.period_size *
6517 out->config.channels *
6518 format_to_bitwidth_table[out->hal_op_format]));
6519 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306520 /*
6521 * To avoid underrun in DSP when the application is not pumping
6522 * data at required rate, check for the no. of bytes and ignore
6523 * pcm_write if it is less than actual buffer size.
6524 * It is a work around to a change in compress VOIP driver.
6525 */
6526 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6527 bytes < (out->config.period_size * out->config.channels *
6528 audio_bytes_per_sample(out->format))) {
6529 size_t voip_buf_size =
6530 out->config.period_size * out->config.channels *
6531 audio_bytes_per_sample(out->format);
6532 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6533 __func__, bytes, voip_buf_size);
6534 usleep(((uint64_t)voip_buf_size - bytes) *
6535 1000000 / audio_stream_out_frame_size(stream) /
6536 out_get_sample_rate(&out->stream.common));
6537 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006538 } else {
6539 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6540 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6541 else
6542 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6543 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306544 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006545
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006546 release_out_focus(out);
6547
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306548 if (ret < 0)
6549 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006550 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306551 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006553 }
6554
6555exit:
Zhou Songc9672822017-08-16 16:01:39 +08006556 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306557 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306558 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006560 pthread_mutex_unlock(&out->lock);
6561
6562 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006563 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006564 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306565 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306566 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306567 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306568 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306569 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306570 out->standby = true;
6571 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306572 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006573 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6574 /* prevent division-by-zero */
6575 uint32_t stream_size = audio_stream_out_frame_size(stream);
6576 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006577
Dieter Luecking5d57def2018-09-07 14:23:37 +02006578 if ((stream_size == 0) || (srate == 0)) {
6579 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6580 ATRACE_END();
6581 return -EINVAL;
6582 }
6583 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6584 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006585 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306586 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006587 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006588 return ret;
6589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006590 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006591 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006592 return bytes;
6593}
6594
6595static int out_get_render_position(const struct audio_stream_out *stream,
6596 uint32_t *dsp_frames)
6597{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006598 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006599
6600 if (dsp_frames == NULL)
6601 return -EINVAL;
6602
6603 *dsp_frames = 0;
6604 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006605 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306606
6607 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6608 * this operation and adev_close_output_stream(where out gets reset).
6609 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306610 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006611 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306612 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006613 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306614 return 0;
6615 }
6616
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006617 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306618 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306619 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006620 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306621 if (ret < 0)
6622 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006623 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306624 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006625 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306626 if (-ENETRESET == ret) {
6627 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306628 out->card_status = CARD_STATUS_OFFLINE;
6629 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306630 } else if(ret < 0) {
6631 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306632 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006633 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6634 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306635 /*
6636 * Handle corner case where compress session is closed during SSR
6637 * and timestamp is queried
6638 */
6639 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306640 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306641 } else if (out->prev_card_status_offline) {
6642 ALOGE("ERROR: previously sound card was offline,return error");
6643 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306644 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306645 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006646 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306647 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306648 pthread_mutex_unlock(&out->lock);
6649 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006650 } else if (audio_is_linear_pcm(out->format)) {
6651 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006652 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006653 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006654 } else
6655 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006656}
6657
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006658static int out_add_audio_effect(const struct audio_stream *stream __unused,
6659 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006660{
6661 return 0;
6662}
6663
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006664static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6665 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006666{
6667 return 0;
6668}
6669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006670static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6671 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006672{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306673 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006674}
6675
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006676static int out_get_presentation_position(const struct audio_stream_out *stream,
6677 uint64_t *frames, struct timespec *timestamp)
6678{
6679 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306680 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006681 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006682
Ashish Jain5106d362016-05-11 19:23:33 +05306683 /* below piece of code is not guarded against any lock because audioFliner serializes
6684 * this operation and adev_close_output_stream( where out gets reset).
6685 */
6686 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306687 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006688 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306689 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6690 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6691 return 0;
6692 }
6693
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006694 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006695
Ashish Jain5106d362016-05-11 19:23:33 +05306696 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6697 ret = compress_get_tstamp(out->compr, &dsp_frames,
6698 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006699 // Adjustment accounts for A2dp encoder latency with offload usecases
6700 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006701 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006702 unsigned long offset =
6703 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6704 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6705 }
Ashish Jain5106d362016-05-11 19:23:33 +05306706 ALOGVV("%s rendered frames %ld sample_rate %d",
6707 __func__, dsp_frames, out->sample_rate);
6708 *frames = dsp_frames;
6709 if (ret < 0)
6710 ret = -errno;
6711 if (-ENETRESET == ret) {
6712 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306713 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306714 ret = -EINVAL;
6715 } else
6716 ret = 0;
6717 /* this is the best we can do */
6718 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006719 } else {
6720 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006721 unsigned int avail;
6722 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006723 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006724 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006725
Andy Hunga1f48fa2019-07-01 18:14:53 -07006726 if (out->kernel_buffer_size > avail) {
6727 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6728 } else {
6729 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6730 __func__, avail, out->kernel_buffer_size);
6731 avail = out->kernel_buffer_size;
6732 frames_temp = out->last_fifo_frames_remaining = 0;
6733 }
6734 out->last_fifo_valid = true;
6735 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6736
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006737 if (out->written >= frames_temp)
6738 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006739
Andy Hunga1f48fa2019-07-01 18:14:53 -07006740 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6741 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6742
Weiyin Jiangd4633762018-03-16 12:05:03 +08006743 // This adjustment accounts for buffering after app processor.
6744 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006745 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006746 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006747 if (signed_frames >= frames_temp)
6748 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006749
Weiyin Jiangd4633762018-03-16 12:05:03 +08006750 // Adjustment accounts for A2dp encoder latency with non offload usecases
6751 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006752 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006753 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6754 if (signed_frames >= frames_temp)
6755 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006756 }
6757
6758 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006759 *frames = signed_frames;
6760 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006761 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006762 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006763 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006764 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006765 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306766 *frames = out->written;
6767 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306768 if (is_offload_usecase(out->usecase))
6769 ret = -EINVAL;
6770 else
6771 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006772 }
6773 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006774 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006775 return ret;
6776}
6777
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006778static int out_set_callback(struct audio_stream_out *stream,
6779 stream_callback_t callback, void *cookie)
6780{
6781 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006782 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006783
6784 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006785 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006786 out->client_callback = callback;
6787 out->client_cookie = cookie;
6788 if (out->adsp_hdlr_stream_handle) {
6789 ret = audio_extn_adsp_hdlr_stream_set_callback(
6790 out->adsp_hdlr_stream_handle,
6791 callback,
6792 cookie);
6793 if (ret)
6794 ALOGW("%s:adsp hdlr callback registration failed %d",
6795 __func__, ret);
6796 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006797 pthread_mutex_unlock(&out->lock);
6798 return 0;
6799}
6800
6801static int out_pause(struct audio_stream_out* stream)
6802{
6803 struct stream_out *out = (struct stream_out *)stream;
6804 int status = -ENOSYS;
6805 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006806 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006807 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306808 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006809 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006810 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006811 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306812 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306813 status = compress_pause(out->compr);
6814
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006815 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006816
Mingming Yin21854652016-04-13 11:54:02 -07006817 if (audio_extn_passthru_is_active()) {
6818 ALOGV("offload use case, pause passthru");
6819 audio_extn_passthru_on_pause(out);
6820 }
6821
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306822 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006823 audio_extn_dts_notify_playback_state(out->usecase, 0,
6824 out->sample_rate, popcount(out->channel_mask),
6825 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006826 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006827 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006828 pthread_mutex_unlock(&out->lock);
6829 }
6830 return status;
6831}
6832
6833static int out_resume(struct audio_stream_out* stream)
6834{
6835 struct stream_out *out = (struct stream_out *)stream;
6836 int status = -ENOSYS;
6837 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006838 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006839 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306840 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006841 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006842 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006843 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306844 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306845 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006846 }
6847 if (!status) {
6848 out->offload_state = OFFLOAD_STATE_PLAYING;
6849 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306850 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006851 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6852 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006853 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006854 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006855 pthread_mutex_unlock(&out->lock);
6856 }
6857 return status;
6858}
6859
6860static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6861{
6862 struct stream_out *out = (struct stream_out *)stream;
6863 int status = -ENOSYS;
6864 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006865 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006866 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006867 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6868 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6869 else
6870 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6871 pthread_mutex_unlock(&out->lock);
6872 }
6873 return status;
6874}
6875
6876static int out_flush(struct audio_stream_out* stream)
6877{
6878 struct stream_out *out = (struct stream_out *)stream;
6879 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006880 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006881 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006882 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006883 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006884 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306885 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006886 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006887 } else {
6888 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306889 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006890 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006891 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006892 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006893 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006894 return 0;
6895 }
6896 return -ENOSYS;
6897}
6898
Haynes Mathew George16081042017-05-31 17:16:49 -07006899static int out_stop(const struct audio_stream_out* stream)
6900{
6901 struct stream_out *out = (struct stream_out *)stream;
6902 struct audio_device *adev = out->dev;
6903 int ret = -ENOSYS;
6904
6905 ALOGV("%s", __func__);
6906 pthread_mutex_lock(&adev->lock);
6907 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6908 out->playback_started && out->pcm != NULL) {
6909 pcm_stop(out->pcm);
6910 ret = stop_output_stream(out);
6911 out->playback_started = false;
6912 }
6913 pthread_mutex_unlock(&adev->lock);
6914 return ret;
6915}
6916
6917static int out_start(const struct audio_stream_out* stream)
6918{
6919 struct stream_out *out = (struct stream_out *)stream;
6920 struct audio_device *adev = out->dev;
6921 int ret = -ENOSYS;
6922
6923 ALOGV("%s", __func__);
6924 pthread_mutex_lock(&adev->lock);
6925 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6926 !out->playback_started && out->pcm != NULL) {
6927 ret = start_output_stream(out);
6928 if (ret == 0) {
6929 out->playback_started = true;
6930 }
6931 }
6932 pthread_mutex_unlock(&adev->lock);
6933 return ret;
6934}
6935
6936/*
6937 * Modify config->period_count based on min_size_frames
6938 */
6939static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6940{
6941 int periodCountRequested = (min_size_frames + config->period_size - 1)
6942 / config->period_size;
6943 int periodCount = MMAP_PERIOD_COUNT_MIN;
6944
6945 ALOGV("%s original config.period_size = %d config.period_count = %d",
6946 __func__, config->period_size, config->period_count);
6947
6948 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6949 periodCount *= 2;
6950 }
6951 config->period_count = periodCount;
6952
6953 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6954}
6955
Phil Burkfe17efd2019-03-25 10:23:35 -07006956// Read offset for the positional timestamp from a persistent vendor property.
6957// This is to workaround apparent inaccuracies in the timing information that
6958// is used by the AAudio timing model. The inaccuracies can cause glitches.
6959static int64_t get_mmap_out_time_offset() {
6960 const int32_t kDefaultOffsetMicros = 0;
6961 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006962 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006963 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6964 return mmap_time_offset_micros * (int64_t)1000;
6965}
6966
Haynes Mathew George16081042017-05-31 17:16:49 -07006967static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6968 int32_t min_size_frames,
6969 struct audio_mmap_buffer_info *info)
6970{
6971 struct stream_out *out = (struct stream_out *)stream;
6972 struct audio_device *adev = out->dev;
6973 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006974 unsigned int offset1 = 0;
6975 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006976 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006977 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006978 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006979
Arun Mirpuri5d170872019-03-26 13:21:31 -07006980 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306981 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006982 pthread_mutex_lock(&adev->lock);
6983
Sharad Sanglec6f32552018-05-04 16:15:38 +05306984 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006985 CARD_STATUS_OFFLINE == adev->card_status ||
6986 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306987 ALOGW("out->card_status or adev->card_status offline, try again");
6988 ret = -EIO;
6989 goto exit;
6990 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306991 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006992 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6993 ret = -EINVAL;
6994 goto exit;
6995 }
6996 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6997 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6998 ret = -ENOSYS;
6999 goto exit;
7000 }
7001 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7002 if (out->pcm_device_id < 0) {
7003 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7004 __func__, out->pcm_device_id, out->usecase);
7005 ret = -EINVAL;
7006 goto exit;
7007 }
7008
7009 adjust_mmap_period_count(&out->config, min_size_frames);
7010
Arun Mirpuri5d170872019-03-26 13:21:31 -07007011 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007012 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7013 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7014 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307015 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307016 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7017 out->card_status = CARD_STATUS_OFFLINE;
7018 adev->card_status = CARD_STATUS_OFFLINE;
7019 ret = -EIO;
7020 goto exit;
7021 }
7022
Haynes Mathew George16081042017-05-31 17:16:49 -07007023 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7024 step = "open";
7025 ret = -ENODEV;
7026 goto exit;
7027 }
7028 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7029 if (ret < 0) {
7030 step = "begin";
7031 goto exit;
7032 }
juyuchen626833d2019-06-04 16:48:02 +08007033
7034 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007035 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007036 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007037 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007038 ret = platform_get_mmap_data_fd(adev->platform,
7039 out->pcm_device_id, 0 /*playback*/,
7040 &info->shared_memory_fd,
7041 &mmap_size);
7042 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007043 // Fall back to non exclusive mode
7044 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7045 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007046 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7047 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7048
Arun Mirpuri5d170872019-03-26 13:21:31 -07007049 if (mmap_size < buffer_size) {
7050 step = "mmap";
7051 goto exit;
7052 }
juyuchen626833d2019-06-04 16:48:02 +08007053 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007054 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007055 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007056 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007057
7058 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7059 if (ret < 0) {
7060 step = "commit";
7061 goto exit;
7062 }
7063
Phil Burkfe17efd2019-03-25 10:23:35 -07007064 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7065
Haynes Mathew George16081042017-05-31 17:16:49 -07007066 out->standby = false;
7067 ret = 0;
7068
Arun Mirpuri5d170872019-03-26 13:21:31 -07007069 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007070 __func__, info->shared_memory_address, info->buffer_size_frames);
7071
7072exit:
7073 if (ret != 0) {
7074 if (out->pcm == NULL) {
7075 ALOGE("%s: %s - %d", __func__, step, ret);
7076 } else {
7077 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7078 pcm_close(out->pcm);
7079 out->pcm = NULL;
7080 }
7081 }
7082 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307083 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007084 return ret;
7085}
7086
7087static int out_get_mmap_position(const struct audio_stream_out *stream,
7088 struct audio_mmap_position *position)
7089{
7090 struct stream_out *out = (struct stream_out *)stream;
7091 ALOGVV("%s", __func__);
7092 if (position == NULL) {
7093 return -EINVAL;
7094 }
7095 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007096 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007097 return -ENOSYS;
7098 }
7099 if (out->pcm == NULL) {
7100 return -ENOSYS;
7101 }
7102
7103 struct timespec ts = { 0, 0 };
7104 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7105 if (ret < 0) {
7106 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7107 return ret;
7108 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007109 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7110 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007111 return 0;
7112}
7113
7114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115/** audio_stream_in implementation **/
7116static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7117{
7118 struct stream_in *in = (struct stream_in *)stream;
7119
7120 return in->config.rate;
7121}
7122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007123static int in_set_sample_rate(struct audio_stream *stream __unused,
7124 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125{
7126 return -ENOSYS;
7127}
7128
7129static size_t in_get_buffer_size(const struct audio_stream *stream)
7130{
7131 struct stream_in *in = (struct stream_in *)stream;
7132
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007133 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7134 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007135 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
7136 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307137 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307138 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007139
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007140 return in->config.period_size * in->af_period_multiplier *
7141 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142}
7143
7144static uint32_t in_get_channels(const struct audio_stream *stream)
7145{
7146 struct stream_in *in = (struct stream_in *)stream;
7147
7148 return in->channel_mask;
7149}
7150
7151static audio_format_t in_get_format(const struct audio_stream *stream)
7152{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007153 struct stream_in *in = (struct stream_in *)stream;
7154
7155 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007156}
7157
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007158static int in_set_format(struct audio_stream *stream __unused,
7159 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007160{
7161 return -ENOSYS;
7162}
7163
7164static int in_standby(struct audio_stream *stream)
7165{
7166 struct stream_in *in = (struct stream_in *)stream;
7167 struct audio_device *adev = in->dev;
7168 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307169 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7170 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007171 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307172
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007173 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007174 if (!in->standby && in->is_st_session) {
7175 ALOGD("%s: sound trigger pcm stop lab", __func__);
7176 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007177 if (adev->num_va_sessions > 0)
7178 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007179 in->standby = 1;
7180 }
7181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007182 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007183 if (adev->adm_deregister_stream)
7184 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7185
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007186 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007188 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007189 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007190 voice_extn_compress_voip_close_input_stream(stream);
7191 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007192 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7193 do_stop = in->capture_started;
7194 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007195 if (in->mmap_shared_memory_fd >= 0) {
7196 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7197 __func__, in->mmap_shared_memory_fd);
7198 close(in->mmap_shared_memory_fd);
7199 in->mmap_shared_memory_fd = -1;
7200 }
Zhou Songa8895042016-07-05 17:54:22 +08007201 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307202 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307203 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007204 }
7205
Arun Mirpuri5d170872019-03-26 13:21:31 -07007206 if (in->pcm) {
7207 ATRACE_BEGIN("pcm_in_close");
7208 pcm_close(in->pcm);
7209 ATRACE_END();
7210 in->pcm = NULL;
7211 }
7212
Carter Hsu2e429db2019-05-14 18:50:52 +08007213 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007214 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007215
George Gao3018ede2019-10-23 13:23:00 -07007216 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7217 if (adev->num_va_sessions > 0)
7218 adev->num_va_sessions--;
7219 }
Quinn Malef6050362019-01-30 15:55:40 -08007220
Eric Laurent150dbfe2013-02-27 14:31:02 -08007221 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007222 }
7223 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007224 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007225 return status;
7226}
7227
Aalique Grahame22e49102018-12-18 14:23:57 -08007228static int in_dump(const struct audio_stream *stream,
7229 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007230{
Aalique Grahame22e49102018-12-18 14:23:57 -08007231 struct stream_in *in = (struct stream_in *)stream;
7232
7233 // We try to get the lock for consistency,
7234 // but it isn't necessary for these variables.
7235 // If we're not in standby, we may be blocked on a read.
7236 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7237 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7238 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7239 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307240#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007241 char buffer[256]; // for statistics formatting
7242 if (in->start_latency_ms.n > 0) {
7243 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7244 dprintf(fd, " Start latency ms: %s\n", buffer);
7245 }
Dechen Chai22768452021-07-30 09:29:16 +05307246#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007247 if (locked) {
7248 pthread_mutex_unlock(&in->lock);
7249 }
Dechen Chai22768452021-07-30 09:29:16 +05307250#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007251 // dump error info
7252 (void)error_log_dump(
7253 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307254#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007255 return 0;
7256}
7257
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307258static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7259{
7260 if (!stream || !parms)
7261 return;
7262
7263 struct stream_in *in = (struct stream_in *)stream;
7264 struct audio_device *adev = in->dev;
7265
7266 card_status_t status;
7267 int card;
7268 if (parse_snd_card_status(parms, &card, &status) < 0)
7269 return;
7270
7271 pthread_mutex_lock(&adev->lock);
7272 bool valid_cb = (card == adev->snd_card);
7273 pthread_mutex_unlock(&adev->lock);
7274
7275 if (!valid_cb)
7276 return;
7277
7278 lock_input_stream(in);
7279 if (in->card_status != status)
7280 in->card_status = status;
7281 pthread_mutex_unlock(&in->lock);
7282
7283 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7284 use_case_table[in->usecase],
7285 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7286
7287 // a better solution would be to report error back to AF and let
7288 // it put the stream to standby
7289 if (status == CARD_STATUS_OFFLINE)
7290 in_standby(&in->stream.common);
7291
7292 return;
7293}
7294
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007295int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007296 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007297 audio_source_t source)
7298{
7299 struct audio_device *adev = in->dev;
7300 int ret = 0;
7301
7302 lock_input_stream(in);
7303 pthread_mutex_lock(&adev->lock);
7304
7305 /* no audio source uses val == 0 */
7306 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7307 in->source = source;
7308 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7309 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7310 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7311 (in->config.rate == 8000 || in->config.rate == 16000 ||
7312 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7313 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7314 ret = voice_extn_compress_voip_open_input_stream(in);
7315 if (ret != 0) {
7316 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7317 __func__, ret);
7318 }
7319 }
7320 }
7321
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007322 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7323 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007324 // Workaround: If routing to an non existing usb device, fail gracefully
7325 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007326 struct str_parms *usb_addr =
7327 str_parms_create_str(get_usb_device_address(devices));
7328 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007329 !audio_extn_usb_connected(NULL)) {
7330 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007331 ret = -ENOSYS;
7332 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007333 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007334 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007335 if (!in->standby && !in->is_st_session) {
7336 ALOGV("update input routing change");
7337 // inform adm before actual routing to prevent glitches.
7338 if (adev->adm_on_routing_change) {
7339 adev->adm_on_routing_change(adev->adm_data,
7340 in->capture_handle);
7341 ret = select_devices(adev, in->usecase);
7342 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7343 adev->adm_routing_changed = true;
7344 }
7345 }
7346 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007347 if (usb_addr)
7348 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007349 }
7350 pthread_mutex_unlock(&adev->lock);
7351 pthread_mutex_unlock(&in->lock);
7352
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007353 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007354 return ret;
7355}
7356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007357static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7358{
7359 struct stream_in *in = (struct stream_in *)stream;
7360 struct audio_device *adev = in->dev;
7361 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307363 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007364
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307365 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007366 parms = str_parms_create_str(kvpairs);
7367
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307368 if (!parms)
7369 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007370 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007371 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007372
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307373 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7374 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307375 strlcpy(in->profile, value, sizeof(in->profile));
7376 ALOGV("updating stream profile with value '%s'", in->profile);
7377 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7378 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007379 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307380 in->sample_rate, in->bit_width,
7381 in->profile, &in->app_type_cfg);
7382 }
7383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007384 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007385 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007386
7387 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307388error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307389 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007390}
7391
7392static char* in_get_parameters(const struct audio_stream *stream,
7393 const char *keys)
7394{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007395 struct stream_in *in = (struct stream_in *)stream;
7396 struct str_parms *query = str_parms_create_str(keys);
7397 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007398 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007399
7400 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007401 if (reply) {
7402 str_parms_destroy(reply);
7403 }
7404 if (query) {
7405 str_parms_destroy(query);
7406 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007407 ALOGE("in_get_parameters: failed to create query or reply");
7408 return NULL;
7409 }
7410
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007411 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007412
7413 voice_extn_in_get_parameters(in, query, reply);
7414
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007415 stream_get_parameter_channels(query, reply,
7416 &in->supported_channel_masks[0]);
7417 stream_get_parameter_formats(query, reply,
7418 &in->supported_formats[0]);
7419 stream_get_parameter_rates(query, reply,
7420 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007421 str = str_parms_to_str(reply);
7422 str_parms_destroy(query);
7423 str_parms_destroy(reply);
7424
7425 ALOGV("%s: exit: returns - %s", __func__, str);
7426 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007427}
7428
Aalique Grahame22e49102018-12-18 14:23:57 -08007429static int in_set_gain(struct audio_stream_in *stream,
7430 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007431{
Aalique Grahame22e49102018-12-18 14:23:57 -08007432 struct stream_in *in = (struct stream_in *)stream;
7433 char mixer_ctl_name[128];
7434 struct mixer_ctl *ctl;
7435 int ctl_value;
7436
7437 ALOGV("%s: gain %f", __func__, gain);
7438
7439 if (stream == NULL)
7440 return -EINVAL;
7441
7442 /* in_set_gain() only used to silence MMAP capture for now */
7443 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7444 return -ENOSYS;
7445
7446 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7447
7448 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7449 if (!ctl) {
7450 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7451 __func__, mixer_ctl_name);
7452 return -ENOSYS;
7453 }
7454
7455 if (gain < RECORD_GAIN_MIN)
7456 gain = RECORD_GAIN_MIN;
7457 else if (gain > RECORD_GAIN_MAX)
7458 gain = RECORD_GAIN_MAX;
7459 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7460
7461 mixer_ctl_set_value(ctl, 0, ctl_value);
7462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007463 return 0;
7464}
7465
7466static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7467 size_t bytes)
7468{
7469 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307470
7471 if (in == NULL) {
7472 ALOGE("%s: stream_in ptr is NULL", __func__);
7473 return -EINVAL;
7474 }
7475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007476 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307477 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307478 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007479
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007480 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307481
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007482 if (in->is_st_session) {
7483 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7484 /* Read from sound trigger HAL */
7485 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007486 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007487 if (adev->num_va_sessions < UINT_MAX)
7488 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007489 in->standby = 0;
7490 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007491 pthread_mutex_unlock(&in->lock);
7492 return bytes;
7493 }
7494
Haynes Mathew George16081042017-05-31 17:16:49 -07007495 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7496 ret = -ENOSYS;
7497 goto exit;
7498 }
7499
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007500 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7501 !in->standby && adev->adm_routing_changed) {
7502 ret = -ENOSYS;
7503 goto exit;
7504 }
7505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007506 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007507 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7508
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007509 pthread_mutex_lock(&adev->lock);
7510 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7511 ret = voice_extn_compress_voip_start_input_stream(in);
7512 else
7513 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007514 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7515 if (adev->num_va_sessions < UINT_MAX)
7516 adev->num_va_sessions++;
7517 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007518 pthread_mutex_unlock(&adev->lock);
7519 if (ret != 0) {
7520 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007521 }
7522 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307523#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007524 // log startup time in ms.
7525 simple_stats_log(
7526 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307527#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007529
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307530 /* Avoid read if capture_stopped is set */
7531 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7532 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7533 ret = -EINVAL;
7534 goto exit;
7535 }
7536
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007537 // what's the duration requested by the client?
7538 long ns = 0;
7539
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307540 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007541 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7542 in->config.rate;
7543
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007544 ret = request_in_focus(in, ns);
7545 if (ret != 0)
7546 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007547 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007548
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307549 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307550 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7551 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307552 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007553 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307554 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007555 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007556 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007557 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007558 } else if (audio_extn_ffv_get_stream() == in) {
7559 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307560 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007561 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307562 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7563 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7564 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7565 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307566 ret = -EINVAL;
7567 goto exit;
7568 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307569 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307570 ret = -errno;
7571 }
7572 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307573 /* bytes read is always set to bytes for non compress usecases */
7574 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007575 }
7576
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007577 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007579 /*
Quinn Malef6050362019-01-30 15:55:40 -08007580 * Instead of writing zeroes here, we could trust the hardware to always
7581 * provide zeroes when muted. This is also muted with voice recognition
7582 * usecases so that other clients do not have access to voice recognition
7583 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007584 */
Quinn Malef6050362019-01-30 15:55:40 -08007585 if ((ret == 0 && voice_get_mic_mute(adev) &&
7586 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007587 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7588 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007589 (adev->num_va_sessions &&
7590 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7591 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7592 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007593 memset(buffer, 0, bytes);
7594
7595exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307596 frame_size = audio_stream_in_frame_size(stream);
7597 if (frame_size > 0)
7598 in->frames_read += bytes_read/frame_size;
7599
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007600 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307601 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007602 pthread_mutex_unlock(&in->lock);
7603
7604 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307605 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307606 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307607 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307608 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307609 in->standby = true;
7610 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307611 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307612 bytes_read = bytes;
7613 memset(buffer, 0, bytes);
7614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007615 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007616 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7617 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007618 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307619 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307620 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007621 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307622 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007623}
7624
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007625static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007626{
7627 return 0;
7628}
7629
Aalique Grahame22e49102018-12-18 14:23:57 -08007630static int in_get_capture_position(const struct audio_stream_in *stream,
7631 int64_t *frames, int64_t *time)
7632{
7633 if (stream == NULL || frames == NULL || time == NULL) {
7634 return -EINVAL;
7635 }
7636 struct stream_in *in = (struct stream_in *)stream;
7637 int ret = -ENOSYS;
7638
7639 lock_input_stream(in);
7640 // note: ST sessions do not close the alsa pcm driver synchronously
7641 // on standby. Therefore, we may return an error even though the
7642 // pcm stream is still opened.
7643 if (in->standby) {
7644 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7645 "%s stream in standby but pcm not NULL for non ST session", __func__);
7646 goto exit;
7647 }
7648 if (in->pcm) {
7649 struct timespec timestamp;
7650 unsigned int avail;
7651 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7652 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007653 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007654 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307655 //Adjustment accounts for A2dp decoder latency for recording usecase
7656 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7657 if (is_a2dp_in_device_type(&in->device_list))
7658 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007659 ret = 0;
7660 }
7661 }
7662exit:
7663 pthread_mutex_unlock(&in->lock);
7664 return ret;
7665}
7666
Carter Hsu2e429db2019-05-14 18:50:52 +08007667static int in_update_effect_list(bool add, effect_handle_t effect,
7668 struct listnode *head)
7669{
7670 struct listnode *node;
7671 struct in_effect_list *elist = NULL;
7672 struct in_effect_list *target = NULL;
7673 int ret = 0;
7674
7675 if (!head)
7676 return ret;
7677
7678 list_for_each(node, head) {
7679 elist = node_to_item(node, struct in_effect_list, list);
7680 if (elist->handle == effect) {
7681 target = elist;
7682 break;
7683 }
7684 }
7685
7686 if (add) {
7687 if (target) {
7688 ALOGD("effect %p already exist", effect);
7689 return ret;
7690 }
7691
7692 target = (struct in_effect_list *)
7693 calloc(1, sizeof(struct in_effect_list));
7694
7695 if (!target) {
7696 ALOGE("%s:fail to allocate memory", __func__);
7697 return -ENOMEM;
7698 }
7699
7700 target->handle = effect;
7701 list_add_tail(head, &target->list);
7702 } else {
7703 if (target) {
7704 list_remove(&target->list);
7705 free(target);
7706 }
7707 }
7708
7709 return ret;
7710}
7711
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007712static int add_remove_audio_effect(const struct audio_stream *stream,
7713 effect_handle_t effect,
7714 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007715{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007716 struct stream_in *in = (struct stream_in *)stream;
7717 int status = 0;
7718 effect_descriptor_t desc;
7719
7720 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007721 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7722
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007723 if (status != 0)
7724 return status;
7725
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007726 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007727 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007728 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007729 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7730 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007731 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007732
7733 in_update_effect_list(enable, effect, &in->aec_list);
7734 enable = !list_empty(&in->aec_list);
7735 if (enable == in->enable_aec)
7736 goto exit;
7737
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007738 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007739 ALOGD("AEC enable %d", enable);
7740
Aalique Grahame22e49102018-12-18 14:23:57 -08007741 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7742 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7743 in->dev->enable_voicerx = enable;
7744 struct audio_usecase *usecase;
7745 struct listnode *node;
7746 list_for_each(node, &in->dev->usecase_list) {
7747 usecase = node_to_item(node, struct audio_usecase, list);
7748 if (usecase->type == PCM_PLAYBACK)
7749 select_devices(in->dev, usecase->id);
7750 }
7751 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007752 if (!in->standby) {
7753 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7754 select_devices(in->dev, in->usecase);
7755 }
7756
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007757 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007758 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7759
7760 in_update_effect_list(enable, effect, &in->ns_list);
7761 enable = !list_empty(&in->ns_list);
7762 if (enable == in->enable_ns)
7763 goto exit;
7764
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007765 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007766 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007767 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007768 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307769 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007770 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007771 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7772 select_devices(in->dev, in->usecase);
7773 } else
7774 select_devices(in->dev, in->usecase);
7775 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007776 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007777exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007778 pthread_mutex_unlock(&in->dev->lock);
7779 pthread_mutex_unlock(&in->lock);
7780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007781 return 0;
7782}
7783
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007784static int in_add_audio_effect(const struct audio_stream *stream,
7785 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007786{
Eric Laurent994a6932013-07-17 11:51:42 -07007787 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007788 return add_remove_audio_effect(stream, effect, true);
7789}
7790
7791static int in_remove_audio_effect(const struct audio_stream *stream,
7792 effect_handle_t effect)
7793{
Eric Laurent994a6932013-07-17 11:51:42 -07007794 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007795 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796}
7797
Haynes Mathew George16081042017-05-31 17:16:49 -07007798static int in_stop(const struct audio_stream_in* stream)
7799{
7800 struct stream_in *in = (struct stream_in *)stream;
7801 struct audio_device *adev = in->dev;
7802
7803 int ret = -ENOSYS;
7804 ALOGV("%s", __func__);
7805 pthread_mutex_lock(&adev->lock);
7806 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7807 in->capture_started && in->pcm != NULL) {
7808 pcm_stop(in->pcm);
7809 ret = stop_input_stream(in);
7810 in->capture_started = false;
7811 }
7812 pthread_mutex_unlock(&adev->lock);
7813 return ret;
7814}
7815
7816static int in_start(const struct audio_stream_in* stream)
7817{
7818 struct stream_in *in = (struct stream_in *)stream;
7819 struct audio_device *adev = in->dev;
7820 int ret = -ENOSYS;
7821
7822 ALOGV("%s in %p", __func__, in);
7823 pthread_mutex_lock(&adev->lock);
7824 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7825 !in->capture_started && in->pcm != NULL) {
7826 if (!in->capture_started) {
7827 ret = start_input_stream(in);
7828 if (ret == 0) {
7829 in->capture_started = true;
7830 }
7831 }
7832 }
7833 pthread_mutex_unlock(&adev->lock);
7834 return ret;
7835}
7836
Phil Burke0a86d12019-02-16 22:28:11 -08007837// Read offset for the positional timestamp from a persistent vendor property.
7838// This is to workaround apparent inaccuracies in the timing information that
7839// is used by the AAudio timing model. The inaccuracies can cause glitches.
7840static int64_t in_get_mmap_time_offset() {
7841 const int32_t kDefaultOffsetMicros = 0;
7842 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007843 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007844 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7845 return mmap_time_offset_micros * (int64_t)1000;
7846}
7847
Haynes Mathew George16081042017-05-31 17:16:49 -07007848static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7849 int32_t min_size_frames,
7850 struct audio_mmap_buffer_info *info)
7851{
7852 struct stream_in *in = (struct stream_in *)stream;
7853 struct audio_device *adev = in->dev;
7854 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007855 unsigned int offset1 = 0;
7856 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007857 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007858 uint32_t mmap_size = 0;
7859 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007860
7861 pthread_mutex_lock(&adev->lock);
7862 ALOGV("%s in %p", __func__, in);
7863
Sharad Sanglec6f32552018-05-04 16:15:38 +05307864 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007865 CARD_STATUS_OFFLINE == adev->card_status ||
7866 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307867 ALOGW("in->card_status or adev->card_status offline, try again");
7868 ret = -EIO;
7869 goto exit;
7870 }
7871
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307872 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007873 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7874 ret = -EINVAL;
7875 goto exit;
7876 }
7877 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7878 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7879 ALOGV("%s in %p", __func__, in);
7880 ret = -ENOSYS;
7881 goto exit;
7882 }
7883 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7884 if (in->pcm_device_id < 0) {
7885 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7886 __func__, in->pcm_device_id, in->usecase);
7887 ret = -EINVAL;
7888 goto exit;
7889 }
7890
7891 adjust_mmap_period_count(&in->config, min_size_frames);
7892
7893 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7894 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7895 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7896 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307897 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307898 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7899 in->card_status = CARD_STATUS_OFFLINE;
7900 adev->card_status = CARD_STATUS_OFFLINE;
7901 ret = -EIO;
7902 goto exit;
7903 }
7904
Haynes Mathew George16081042017-05-31 17:16:49 -07007905 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7906 step = "open";
7907 ret = -ENODEV;
7908 goto exit;
7909 }
7910
7911 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7912 if (ret < 0) {
7913 step = "begin";
7914 goto exit;
7915 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007916
juyuchen626833d2019-06-04 16:48:02 +08007917 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007918 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7919 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7920 info->burst_size_frames = in->config.period_size;
7921 ret = platform_get_mmap_data_fd(adev->platform,
7922 in->pcm_device_id, 1 /*capture*/,
7923 &info->shared_memory_fd,
7924 &mmap_size);
7925 if (ret < 0) {
7926 // Fall back to non exclusive mode
7927 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7928 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007929 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7930 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7931
Arun Mirpuri5d170872019-03-26 13:21:31 -07007932 if (mmap_size < buffer_size) {
7933 step = "mmap";
7934 goto exit;
7935 }
juyuchen626833d2019-06-04 16:48:02 +08007936 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007937 }
7938
7939 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007940
7941 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7942 if (ret < 0) {
7943 step = "commit";
7944 goto exit;
7945 }
7946
Phil Burke0a86d12019-02-16 22:28:11 -08007947 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7948
Haynes Mathew George16081042017-05-31 17:16:49 -07007949 in->standby = false;
7950 ret = 0;
7951
7952 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7953 __func__, info->shared_memory_address, info->buffer_size_frames);
7954
7955exit:
7956 if (ret != 0) {
7957 if (in->pcm == NULL) {
7958 ALOGE("%s: %s - %d", __func__, step, ret);
7959 } else {
7960 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7961 pcm_close(in->pcm);
7962 in->pcm = NULL;
7963 }
7964 }
7965 pthread_mutex_unlock(&adev->lock);
7966 return ret;
7967}
7968
7969static int in_get_mmap_position(const struct audio_stream_in *stream,
7970 struct audio_mmap_position *position)
7971{
7972 struct stream_in *in = (struct stream_in *)stream;
7973 ALOGVV("%s", __func__);
7974 if (position == NULL) {
7975 return -EINVAL;
7976 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307977 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007978 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307979 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007980 return -ENOSYS;
7981 }
7982 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307983 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007984 return -ENOSYS;
7985 }
7986 struct timespec ts = { 0, 0 };
7987 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7988 if (ret < 0) {
7989 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307990 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007991 return ret;
7992 }
Phil Burke0a86d12019-02-16 22:28:11 -08007993 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7994 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307995 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007996 return 0;
7997}
7998
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307999static int in_get_active_microphones(const struct audio_stream_in *stream,
8000 struct audio_microphone_characteristic_t *mic_array,
8001 size_t *mic_count) {
8002 struct stream_in *in = (struct stream_in *)stream;
8003 struct audio_device *adev = in->dev;
8004 ALOGVV("%s", __func__);
8005
8006 lock_input_stream(in);
8007 pthread_mutex_lock(&adev->lock);
8008 int ret = platform_get_active_microphones(adev->platform,
8009 audio_channel_count_from_in_mask(in->channel_mask),
8010 in->usecase, mic_array, mic_count);
8011 pthread_mutex_unlock(&adev->lock);
8012 pthread_mutex_unlock(&in->lock);
8013
8014 return ret;
8015}
8016
8017static int adev_get_microphones(const struct audio_hw_device *dev,
8018 struct audio_microphone_characteristic_t *mic_array,
8019 size_t *mic_count) {
8020 struct audio_device *adev = (struct audio_device *)dev;
8021 ALOGVV("%s", __func__);
8022
8023 pthread_mutex_lock(&adev->lock);
8024 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8025 pthread_mutex_unlock(&adev->lock);
8026
8027 return ret;
8028}
juyuchendb308c22019-01-21 11:57:17 -07008029
8030static void in_update_sink_metadata(struct audio_stream_in *stream,
8031 const struct sink_metadata *sink_metadata) {
8032
8033 if (stream == NULL
8034 || sink_metadata == NULL
8035 || sink_metadata->tracks == NULL) {
8036 return;
8037 }
8038
8039 int error = 0;
8040 struct stream_in *in = (struct stream_in *)stream;
8041 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008042 struct listnode devices;
8043
8044 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008045
8046 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008047 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008048
8049 lock_input_stream(in);
8050 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008051 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008052
Zhou Song503196b2021-07-23 17:31:05 +08008053 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8054 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8055 !list_empty(&devices) &&
8056 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008057 /* Use the rx device from afe-proxy record to route voice call because
8058 there is no routing if tx device is on primary hal and rx device
8059 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008060 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008061
8062 if (!voice_is_call_state_active(adev)) {
8063 if (adev->mode == AUDIO_MODE_IN_CALL) {
8064 adev->current_call_output = adev->voice_tx_output;
8065 error = voice_start_call(adev);
8066 if (error != 0)
8067 ALOGE("%s: start voice call failed %d", __func__, error);
8068 }
8069 } else {
8070 adev->current_call_output = adev->voice_tx_output;
8071 voice_update_devices_for_all_voice_usecases(adev);
8072 }
8073 }
8074
Zhenlin Lian4f947842022-05-14 15:50:52 +05308075 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008076 pthread_mutex_unlock(&adev->lock);
8077 pthread_mutex_unlock(&in->lock);
8078}
8079
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308080int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008081 audio_io_handle_t handle,
8082 audio_devices_t devices,
8083 audio_output_flags_t flags,
8084 struct audio_config *config,
8085 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008086 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008087{
8088 struct audio_device *adev = (struct audio_device *)dev;
8089 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308090 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008091 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008092 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308093 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008094 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8095 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8096 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8097 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008098 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008099 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8100 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008101 bool force_haptic_path =
8102 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008103 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008104#ifdef AUDIO_GKI_ENABLED
8105 __s32 *generic_dec;
8106#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008107 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008108
kunleizdff872d2018-08-20 14:40:33 +08008109 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008110 is_usb_dev = false;
8111 devices = AUDIO_DEVICE_OUT_SPEAKER;
8112 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8113 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008114 if (config->format == AUDIO_FORMAT_DEFAULT)
8115 config->format = AUDIO_FORMAT_PCM_16_BIT;
8116 if (config->sample_rate == 0)
8117 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8118 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8119 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008120 }
8121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008122 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008124 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8125
Mingming Yin3a941d42016-02-17 18:08:05 -08008126 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008127 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8128 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308129
8130
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008131 if (!out) {
8132 return -ENOMEM;
8133 }
8134
Haynes Mathew George204045b2015-02-25 20:32:03 -08008135 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008136 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008137 pthread_mutexattr_init(&latch_attr);
8138 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8139 pthread_mutex_init(&out->latch_lock, &latch_attr);
8140 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008141 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008142 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008144 if (devices == AUDIO_DEVICE_NONE)
8145 devices = AUDIO_DEVICE_OUT_SPEAKER;
8146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008147 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008148 list_init(&out->device_list);
8149 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008150 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008151 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008152 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308153 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308154 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8155 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8156 else
8157 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008158 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008159 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008160 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308161 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308162 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008163 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008164 out->hal_output_suspend_supported = 0;
8165 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308166 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308167 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308168 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008169 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008170
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308171 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308172 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008173 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8174
Aalique Grahame22e49102018-12-18 14:23:57 -08008175 if (direct_dev &&
8176 (audio_is_linear_pcm(out->format) ||
8177 config->format == AUDIO_FORMAT_DEFAULT) &&
8178 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8179 audio_format_t req_format = config->format;
8180 audio_channel_mask_t req_channel_mask = config->channel_mask;
8181 uint32_t req_sample_rate = config->sample_rate;
8182
8183 pthread_mutex_lock(&adev->lock);
8184 if (is_hdmi) {
8185 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8186 ret = read_hdmi_sink_caps(out);
8187 if (config->sample_rate == 0)
8188 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8189 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8190 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8191 if (config->format == AUDIO_FORMAT_DEFAULT)
8192 config->format = AUDIO_FORMAT_PCM_16_BIT;
8193 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008194 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8195 &config->format,
8196 &out->supported_formats[0],
8197 MAX_SUPPORTED_FORMATS,
8198 &config->channel_mask,
8199 &out->supported_channel_masks[0],
8200 MAX_SUPPORTED_CHANNEL_MASKS,
8201 &config->sample_rate,
8202 &out->supported_sample_rates[0],
8203 MAX_SUPPORTED_SAMPLE_RATES);
8204 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008205 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008206
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008207 pthread_mutex_unlock(&adev->lock);
8208 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008209 if (ret == -ENOSYS) {
8210 /* ignore and go with default */
8211 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008212 }
8213 // For MMAP NO IRQ, allow conversions in ADSP
8214 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8215 goto error_open;
8216 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008217 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008218 goto error_open;
8219 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008220
8221 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8222 config->sample_rate = req_sample_rate;
8223 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8224 config->channel_mask = req_channel_mask;
8225 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8226 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008227 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008228
8229 out->sample_rate = config->sample_rate;
8230 out->channel_mask = config->channel_mask;
8231 out->format = config->format;
8232 if (is_hdmi) {
8233 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8234 out->config = pcm_config_hdmi_multi;
8235 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8236 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8237 out->config = pcm_config_mmap_playback;
8238 out->stream.start = out_start;
8239 out->stream.stop = out_stop;
8240 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8241 out->stream.get_mmap_position = out_get_mmap_position;
8242 } else {
8243 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8244 out->config = pcm_config_hifi;
8245 }
8246
8247 out->config.rate = out->sample_rate;
8248 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8249 if (is_hdmi) {
8250 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8251 audio_bytes_per_sample(out->format));
8252 }
8253 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008254 }
8255
Derek Chenf6318be2017-06-12 17:16:24 -04008256 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008257 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008258 /* extract car audio stream index */
8259 out->car_audio_stream =
8260 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8261 if (out->car_audio_stream < 0) {
8262 ALOGE("%s: invalid car audio stream %x",
8263 __func__, out->car_audio_stream);
8264 ret = -EINVAL;
8265 goto error_open;
8266 }
Derek Chen5f67a942020-02-24 23:08:13 -08008267 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008268 }
8269
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008270 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008271 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008272 if (!voice_extn_is_compress_voip_supported()) {
8273 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8274 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008275 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308276 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008277 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8278 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008279 out->volume_l = INVALID_OUT_VOLUME;
8280 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008281
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008282 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008283 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008284 uint32_t channel_count =
8285 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308286 out->config.channels = channel_count;
8287
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008288 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8289 out->sample_rate, out->format,
8290 channel_count, false);
8291 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8292 if (frame_size != 0)
8293 out->config.period_size = buffer_size / frame_size;
8294 else
8295 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008296 }
8297 } else {
8298 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8299 voice_extn_compress_voip_is_active(out->dev)) &&
8300 (voice_extn_compress_voip_is_config_supported(config))) {
8301 ret = voice_extn_compress_voip_open_output_stream(out);
8302 if (ret != 0) {
8303 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8304 __func__, ret);
8305 goto error_open;
8306 }
Sujin Panicker19027262019-09-16 18:28:06 +05308307 } else {
8308 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8309 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008310 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008311 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008312 } else if (audio_is_linear_pcm(out->format) &&
8313 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8314 out->channel_mask = config->channel_mask;
8315 out->sample_rate = config->sample_rate;
8316 out->format = config->format;
8317 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8318 // does this change?
8319 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8320 out->config.rate = config->sample_rate;
8321 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8322 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8323 audio_bytes_per_sample(config->format));
8324 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008325 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308326 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308327 pthread_mutex_lock(&adev->lock);
8328 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8329 pthread_mutex_unlock(&adev->lock);
8330
8331 // reject offload during card offline to allow
8332 // fallback to s/w paths
8333 if (offline) {
8334 ret = -ENODEV;
8335 goto error_open;
8336 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008337
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008338 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8339 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8340 ALOGE("%s: Unsupported Offload information", __func__);
8341 ret = -EINVAL;
8342 goto error_open;
8343 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008344
Atul Khare3fa6e542017-08-09 00:56:17 +05308345 if (config->offload_info.format == 0)
8346 config->offload_info.format = config->format;
8347 if (config->offload_info.sample_rate == 0)
8348 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008349
Mingming Yin90310102013-11-13 16:57:00 -08008350 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308351 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008352 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008353 ret = -EINVAL;
8354 goto error_open;
8355 }
8356
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008357 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8358 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8359 (audio_extn_passthru_is_passthrough_stream(out)) &&
8360 !((config->sample_rate == 48000) ||
8361 (config->sample_rate == 96000) ||
8362 (config->sample_rate == 192000))) {
8363 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8364 __func__, config->sample_rate, config->offload_info.format);
8365 ret = -EINVAL;
8366 goto error_open;
8367 }
8368
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008369 out->compr_config.codec = (struct snd_codec *)
8370 calloc(1, sizeof(struct snd_codec));
8371
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008372 if (!out->compr_config.codec) {
8373 ret = -ENOMEM;
8374 goto error_open;
8375 }
8376
Dhananjay Kumarac341582017-02-23 23:42:25 +05308377 out->stream.pause = out_pause;
8378 out->stream.resume = out_resume;
8379 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308380 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308381 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008382 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308383 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008384 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308385 } else {
8386 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8387 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008388 }
vivek mehta446c3962015-09-14 10:57:35 -07008389
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308390 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8391 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008392#ifdef AUDIO_GKI_ENABLED
8393 /* out->compr_config.codec->reserved[1] is for flags */
8394 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8395#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308396 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008397#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308398 }
8399
vivek mehta446c3962015-09-14 10:57:35 -07008400 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008401 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008402 config->format == 0 && config->sample_rate == 0 &&
8403 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008404 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008405 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8406 } else {
8407 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8408 ret = -EEXIST;
8409 goto error_open;
8410 }
vivek mehta446c3962015-09-14 10:57:35 -07008411 }
8412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008413 if (config->offload_info.channel_mask)
8414 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008415 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008416 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008417 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008418 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308419 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008420 ret = -EINVAL;
8421 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008422 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008423
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008424 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008425 out->sample_rate = config->offload_info.sample_rate;
8426
Mingming Yin3ee55c62014-08-04 14:23:35 -07008427 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008428
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308429 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308430 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308431 audio_extn_dolby_send_ddp_endp_params(adev);
8432 audio_extn_dolby_set_dmid(adev);
8433 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008434
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008435 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008436 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008437 out->compr_config.codec->bit_rate =
8438 config->offload_info.bit_rate;
8439 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308440 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008441 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308442 /* Update bit width only for non passthrough usecases.
8443 * For passthrough usecases, the output will always be opened @16 bit
8444 */
8445 if (!audio_extn_passthru_is_passthrough_stream(out))
8446 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308447
8448 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008449#ifdef AUDIO_GKI_ENABLED
8450 /* out->compr_config.codec->reserved[1] is for flags */
8451 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8452 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8453#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308454 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8455 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008456#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308457
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008458 /*TODO: Do we need to change it for passthrough */
8459 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008460
Manish Dewangana6fc5442015-08-24 20:30:31 +05308461 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8462 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308463 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308464 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308465 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8466 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308467
8468 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8469 AUDIO_FORMAT_PCM) {
8470
8471 /*Based on platform support, configure appropriate alsa format for corresponding
8472 *hal input format.
8473 */
8474 out->compr_config.codec->format = hal_format_to_alsa(
8475 config->offload_info.format);
8476
Ashish Jain83a6cc22016-06-28 14:34:17 +05308477 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308478 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308479 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308480
Dhananjay Kumarac341582017-02-23 23:42:25 +05308481 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308482 *hal input format and alsa format might differ based on platform support.
8483 */
8484 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308485 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308486
8487 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8488
Deeraj Soman93155a62019-09-30 19:00:37 +05308489 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8490 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8491 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8492 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8493 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308494
Ashish Jainf1eaa582016-05-23 20:54:24 +05308495 /* Check if alsa session is configured with the same format as HAL input format,
8496 * if not then derive correct fragment size needed to accomodate the
8497 * conversion of HAL input format to alsa format.
8498 */
8499 audio_extn_utils_update_direct_pcm_fragment_size(out);
8500
8501 /*if hal input and output fragment size is different this indicates HAL input format is
8502 *not same as the alsa format
8503 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308504 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308505 /*Allocate a buffer to convert input data to the alsa configured format.
8506 *size of convert buffer is equal to the size required to hold one fragment size
8507 *worth of pcm data, this is because flinger does not write more than fragment_size
8508 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308509 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8510 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308511 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8512 ret = -ENOMEM;
8513 goto error_open;
8514 }
8515 }
8516 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8517 out->compr_config.fragment_size =
8518 audio_extn_passthru_get_buffer_size(&config->offload_info);
8519 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8520 } else {
8521 out->compr_config.fragment_size =
8522 platform_get_compress_offload_buffer_size(&config->offload_info);
8523 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8524 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008525
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308526 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8527 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8528 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008529 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8530#ifdef AUDIO_GKI_ENABLED
8531 generic_dec =
8532 &(out->compr_config.codec->options.generic.reserved[1]);
8533 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8534 AUDIO_OUTPUT_BIT_WIDTH;
8535#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308536 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008537#endif
8538 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008539
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308540 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8541 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8542 }
8543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008544 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8545 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008546
Manish Dewangan69426c82017-01-30 17:35:36 +05308547 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8548 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8549 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8550 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8551 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8552 } else {
8553 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8554 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008555
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308556 memset(&out->channel_map_param, 0,
8557 sizeof(struct audio_out_channel_map_param));
8558
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008559 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308560 out->send_next_track_params = false;
8561 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008562 out->offload_state = OFFLOAD_STATE_IDLE;
8563 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008564 out->writeAt.tv_sec = 0;
8565 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008566
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008567 audio_extn_dts_create_state_notifier_node(out->usecase);
8568
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008569 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8570 __func__, config->offload_info.version,
8571 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308572
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308573 /* Check if DSD audio format is supported in codec
8574 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308575 */
8576
8577 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308578 (!platform_check_codec_dsd_support(adev->platform) ||
8579 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308580 ret = -EINVAL;
8581 goto error_open;
8582 }
8583
Ashish Jain5106d362016-05-11 19:23:33 +05308584 /* Disable gapless if any of the following is true
8585 * passthrough playback
8586 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308587 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308588 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308589 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308590 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008591 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308592 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308593 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308594 check_and_set_gapless_mode(adev, false);
8595 } else
8596 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008597
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308598 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008599 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8600 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308601 if (config->format == AUDIO_FORMAT_DSD) {
8602 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008603#ifdef AUDIO_GKI_ENABLED
8604 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8605 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8606#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308607 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008608#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308609 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008610
8611 create_offload_callback_thread(out);
8612
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008613 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008614 switch (config->sample_rate) {
8615 case 0:
8616 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8617 break;
8618 case 8000:
8619 case 16000:
8620 case 48000:
8621 out->sample_rate = config->sample_rate;
8622 break;
8623 default:
8624 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8625 config->sample_rate);
8626 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8627 ret = -EINVAL;
8628 goto error_open;
8629 }
8630 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8631 switch (config->channel_mask) {
8632 case AUDIO_CHANNEL_NONE:
8633 case AUDIO_CHANNEL_OUT_STEREO:
8634 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8635 break;
8636 default:
8637 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8638 config->channel_mask);
8639 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8640 ret = -EINVAL;
8641 goto error_open;
8642 }
8643 switch (config->format) {
8644 case AUDIO_FORMAT_DEFAULT:
8645 case AUDIO_FORMAT_PCM_16_BIT:
8646 out->format = AUDIO_FORMAT_PCM_16_BIT;
8647 break;
8648 default:
8649 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8650 config->format);
8651 config->format = AUDIO_FORMAT_PCM_16_BIT;
8652 ret = -EINVAL;
8653 goto error_open;
8654 }
8655
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308656 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008657 if (ret != 0) {
8658 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008659 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008660 goto error_open;
8661 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008662 } else if (is_single_device_type_equal(&out->device_list,
8663 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008664 switch (config->sample_rate) {
8665 case 0:
8666 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8667 break;
8668 case 8000:
8669 case 16000:
8670 case 48000:
8671 out->sample_rate = config->sample_rate;
8672 break;
8673 default:
8674 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8675 config->sample_rate);
8676 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8677 ret = -EINVAL;
8678 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008679 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008680 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8681 switch (config->channel_mask) {
8682 case AUDIO_CHANNEL_NONE:
8683 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8684 break;
8685 case AUDIO_CHANNEL_OUT_STEREO:
8686 out->channel_mask = config->channel_mask;
8687 break;
8688 default:
8689 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8690 config->channel_mask);
8691 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8692 ret = -EINVAL;
8693 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008694 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008695 switch (config->format) {
8696 case AUDIO_FORMAT_DEFAULT:
8697 out->format = AUDIO_FORMAT_PCM_16_BIT;
8698 break;
8699 case AUDIO_FORMAT_PCM_16_BIT:
8700 out->format = config->format;
8701 break;
8702 default:
8703 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8704 config->format);
8705 config->format = AUDIO_FORMAT_PCM_16_BIT;
8706 ret = -EINVAL;
8707 break;
8708 }
8709 if (ret != 0)
8710 goto error_open;
8711
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008712 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8713 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008714 out->config.rate = out->sample_rate;
8715 out->config.channels =
8716 audio_channel_count_from_out_mask(out->channel_mask);
8717 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008718 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008719 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308720 unsigned int channels = 0;
8721 /*Update config params to default if not set by the caller*/
8722 if (config->sample_rate == 0)
8723 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8724 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8725 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8726 if (config->format == AUDIO_FORMAT_DEFAULT)
8727 config->format = AUDIO_FORMAT_PCM_16_BIT;
8728
8729 channels = audio_channel_count_from_out_mask(out->channel_mask);
8730
Varun Balaraje49253e2017-07-06 19:48:56 +05308731 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8732 out->usecase = get_interactive_usecase(adev);
8733 out->config = pcm_config_low_latency;
8734 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308735 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008736 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8737 out->flags);
8738 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008739 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8740 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8741 out->config = pcm_config_mmap_playback;
8742 out->stream.start = out_start;
8743 out->stream.stop = out_stop;
8744 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8745 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308746 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8747 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008748 out->hal_output_suspend_supported =
8749 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8750 out->dynamic_pm_qos_config_supported =
8751 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8752 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008753 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8754 } else {
8755 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8756 //the mixer path will be a string similar to "low-latency-playback resume"
8757 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8758 strlcat(out->pm_qos_mixer_path,
8759 " resume", MAX_MIXER_PATH_LEN);
8760 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8761 out->pm_qos_mixer_path);
8762 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308763 out->config = pcm_config_low_latency;
8764 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8765 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8766 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308767 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8768 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8769 if (out->config.period_size <= 0) {
8770 ALOGE("Invalid configuration period size is not valid");
8771 ret = -EINVAL;
8772 goto error_open;
8773 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008774 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8775 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8776 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008777 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8778 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8779 out->config = pcm_config_haptics_audio;
8780 if (force_haptic_path)
8781 adev->haptics_config = pcm_config_haptics_audio;
8782 else
8783 adev->haptics_config = pcm_config_haptics;
8784
Meng Wangd08ce322020-04-02 08:59:20 +08008785 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008786 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8787
8788 if (force_haptic_path) {
8789 out->config.channels = 1;
8790 adev->haptics_config.channels = 1;
8791 } else
8792 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 -08008793 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008794 ret = audio_extn_auto_hal_open_output_stream(out);
8795 if (ret) {
8796 ALOGE("%s: Failed to open output stream for bus device", __func__);
8797 ret = -EINVAL;
8798 goto error_open;
8799 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308800 } else {
8801 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008802 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8803 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308804 }
8805 out->hal_ip_format = format = out->format;
8806 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8807 out->hal_op_format = pcm_format_to_hal(out->config.format);
8808 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8809 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008810 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308811 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308812 if (out->hal_ip_format != out->hal_op_format) {
8813 uint32_t buffer_size = out->config.period_size *
8814 format_to_bitwidth_table[out->hal_op_format] *
8815 out->config.channels;
8816 out->convert_buffer = calloc(1, buffer_size);
8817 if (out->convert_buffer == NULL){
8818 ALOGE("Allocation failed for convert buffer for size %d",
8819 out->compr_config.fragment_size);
8820 ret = -ENOMEM;
8821 goto error_open;
8822 }
8823 ALOGD("Convert buffer allocated of size %d", buffer_size);
8824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008825 }
8826
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008827 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8828 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308829
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008830 /* TODO remove this hardcoding and check why width is zero*/
8831 if (out->bit_width == 0)
8832 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308833 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008834 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008835 &out->device_list, out->flags,
8836 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308837 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308838 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008839 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008840 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8841 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008842 if(adev->primary_output == NULL)
8843 adev->primary_output = out;
8844 else {
8845 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008846 ret = -EEXIST;
8847 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008848 }
8849 }
8850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008851 /* Check if this usecase is already existing */
8852 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008853 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8854 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008855 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008856 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008857 ret = -EEXIST;
8858 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008859 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008861 pthread_mutex_unlock(&adev->lock);
8862
8863 out->stream.common.get_sample_rate = out_get_sample_rate;
8864 out->stream.common.set_sample_rate = out_set_sample_rate;
8865 out->stream.common.get_buffer_size = out_get_buffer_size;
8866 out->stream.common.get_channels = out_get_channels;
8867 out->stream.common.get_format = out_get_format;
8868 out->stream.common.set_format = out_set_format;
8869 out->stream.common.standby = out_standby;
8870 out->stream.common.dump = out_dump;
8871 out->stream.common.set_parameters = out_set_parameters;
8872 out->stream.common.get_parameters = out_get_parameters;
8873 out->stream.common.add_audio_effect = out_add_audio_effect;
8874 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8875 out->stream.get_latency = out_get_latency;
8876 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008877#ifdef NO_AUDIO_OUT
8878 out->stream.write = out_write_for_no_output;
8879#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008881#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008882 out->stream.get_render_position = out_get_render_position;
8883 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008884 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885
Haynes Mathew George16081042017-05-31 17:16:49 -07008886 if (out->realtime)
8887 out->af_period_multiplier = af_period_multiplier;
8888 else
8889 out->af_period_multiplier = 1;
8890
Andy Hunga1f48fa2019-07-01 18:14:53 -07008891 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008893 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008894 out->volume_l = PLAYBACK_GAIN_MAX;
8895 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008896 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008897 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008898
8899 config->format = out->stream.common.get_format(&out->stream.common);
8900 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8901 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308902 register_format(out->format, out->supported_formats);
8903 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8904 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008905
Dechen Chai22768452021-07-30 09:29:16 +05308906#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008907 out->error_log = error_log_create(
8908 ERROR_LOG_ENTRIES,
8909 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308910#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308911 /*
8912 By locking output stream before registering, we allow the callback
8913 to update stream's state only after stream's initial state is set to
8914 adev state.
8915 */
8916 lock_output_stream(out);
8917 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8918 pthread_mutex_lock(&adev->lock);
8919 out->card_status = adev->card_status;
8920 pthread_mutex_unlock(&adev->lock);
8921 pthread_mutex_unlock(&out->lock);
8922
Aalique Grahame22e49102018-12-18 14:23:57 -08008923 stream_app_type_cfg_init(&out->app_type_cfg);
8924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008925 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308926 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008927 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008928
8929 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8930 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8931 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008932 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308933 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008934 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008935 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308936 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8937 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008938 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8939 out->usecase, PCM_PLAYBACK);
8940 hdlr_stream_cfg.flags = out->flags;
8941 hdlr_stream_cfg.type = PCM_PLAYBACK;
8942 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8943 &hdlr_stream_cfg);
8944 if (ret) {
8945 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8946 out->adsp_hdlr_stream_handle = NULL;
8947 }
8948 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308949 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8950 is_direct_passthough, false);
8951 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8952 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008953 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008954 if (ret < 0) {
8955 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8956 out->ip_hdlr_handle = NULL;
8957 }
8958 }
Derek Chenf939fb72018-11-13 13:34:41 -08008959
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008960 ret = io_streams_map_insert(adev, &out->stream.common,
8961 out->handle, AUDIO_PATCH_HANDLE_NONE);
8962 if (ret != 0)
8963 goto error_open;
8964
Susan Wang6dd13092021-01-25 10:27:11 -05008965 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008966
8967 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008968 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008969 pthread_mutex_unlock(&adev->lock);
8970
Eric Laurent994a6932013-07-17 11:51:42 -07008971 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008972 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008973
8974error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308975 if (out->convert_buffer)
8976 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008977 free(out);
8978 *stream_out = NULL;
8979 ALOGD("%s: exit: ret %d", __func__, ret);
8980 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008981}
8982
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308983void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008984 struct audio_stream_out *stream)
8985{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008986 struct stream_out *out = (struct stream_out *)stream;
8987 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008988 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008989
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008990 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308991
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008992 io_streams_map_remove(adev, out->handle);
8993
Susan Wang6dd13092021-01-25 10:27:11 -05008994 // remove out_ctxt early to prevent the stream
8995 // being opened in a race condition
8996 pthread_mutex_lock(&adev->lock);
8997 list_remove(&out->out_ctxt.list);
8998 pthread_mutex_unlock(&adev->lock);
8999
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309000 // must deregister from sndmonitor first to prevent races
9001 // between the callback and close_stream
9002 audio_extn_snd_mon_unregister_listener(out);
9003
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009004 /* close adsp hdrl session before standby */
9005 if (out->adsp_hdlr_stream_handle) {
9006 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9007 if (ret)
9008 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9009 out->adsp_hdlr_stream_handle = NULL;
9010 }
9011
Manish Dewangan21a850a2017-08-14 12:03:55 +05309012 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009013 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9014 out->ip_hdlr_handle = NULL;
9015 }
9016
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009017 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309018 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009019 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309020 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309021 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009022 if(ret != 0)
9023 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9024 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009025 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009026 out_standby(&stream->common);
9027
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009028 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009029 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009030 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009031 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009032 if (out->compr_config.codec != NULL)
9033 free(out->compr_config.codec);
9034 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009035
Zhou Songbaddf9f2020-11-20 13:57:39 +08009036 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309037
Varun Balaraje49253e2017-07-06 19:48:56 +05309038 if (is_interactive_usecase(out->usecase))
9039 free_interactive_usecase(adev, out->usecase);
9040
Ashish Jain83a6cc22016-06-28 14:34:17 +05309041 if (out->convert_buffer != NULL) {
9042 free(out->convert_buffer);
9043 out->convert_buffer = NULL;
9044 }
9045
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009046 if (adev->voice_tx_output == out)
9047 adev->voice_tx_output = NULL;
9048
Dechen Chai22768452021-07-30 09:29:16 +05309049#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009050 error_log_destroy(out->error_log);
9051 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309052#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309053 if (adev->primary_output == out)
9054 adev->primary_output = NULL;
9055
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009056 pthread_cond_destroy(&out->cond);
9057 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009058 pthread_mutex_destroy(&out->pre_lock);
9059 pthread_mutex_destroy(&out->latch_lock);
9060 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009061
9062 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309063 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009064 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009065 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009066 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009067}
9068
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009069void in_set_power_policy(uint8_t enable)
9070{
9071 struct listnode *node;
9072
9073 ALOGD("%s: Enter, state %d", __func__, enable);
9074
9075 pthread_mutex_lock(&adev->lock);
9076 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9077 pthread_mutex_unlock(&adev->lock);
9078
9079 if (!enable) {
9080 list_for_each(node, &adev->active_inputs_list) {
9081 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9082 streams_input_ctxt_t,
9083 list);
9084 struct stream_in *in = in_ctxt->input;
9085 in_standby(&in->stream.common);
9086 }
9087 }
9088
9089 ALOGD("%s: Exit", __func__);
9090}
9091
9092void out_set_power_policy(uint8_t enable)
9093{
9094 struct listnode *node;
9095
9096 ALOGD("%s: Enter, state %d", __func__, enable);
9097
9098 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309099 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009100 pthread_mutex_unlock(&adev->lock);
9101
9102 if (!enable) {
9103 list_for_each(node, &adev->active_outputs_list) {
9104 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9105 streams_output_ctxt_t,
9106 list);
9107 struct stream_out *out = out_ctxt->output;
9108 out_on_error(&out->stream.common);
9109 }
9110 }
9111
9112 ALOGD("%s: Exit", __func__);
9113}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009114static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9115{
9116 struct audio_device *adev = (struct audio_device *)dev;
9117 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009118 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009119 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009120 int ret;
9121 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009122 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009123 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009124 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009125
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009126 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009127 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009128
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309129 if (!parms)
9130 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309131
Derek Chen6f293672019-04-01 01:40:24 -07009132 /* notify adev and input/output streams on the snd card status */
9133 adev_snd_mon_cb((void *)adev, parms);
9134
Weiyin Jiang24f55292020-12-22 14:35:46 +08009135 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9136 if (ret >= 0) {
9137 list_for_each(node, &adev->active_outputs_list) {
9138 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9139 streams_output_ctxt_t,
9140 list);
9141 out_snd_mon_cb((void *)out_ctxt->output, parms);
9142 }
Derek Chen6f293672019-04-01 01:40:24 -07009143
Weiyin Jiang24f55292020-12-22 14:35:46 +08009144 list_for_each(node, &adev->active_inputs_list) {
9145 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9146 streams_input_ctxt_t,
9147 list);
9148 in_snd_mon_cb((void *)in_ctxt->input, parms);
9149 }
Derek Chen6f293672019-04-01 01:40:24 -07009150 }
9151
Zhou Songd6d71752019-05-21 18:08:51 +08009152 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309153 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9154 if (ret >= 0) {
9155 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009156 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309157 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309158 /*
9159 * When ever BT_SCO=ON arrives, make sure to route
9160 * all use cases to SCO device, otherwise due to delay in
9161 * BT_SCO=ON and lack of synchronization with create audio patch
9162 * request for SCO device, some times use case not routed properly to
9163 * SCO device
9164 */
9165 struct audio_usecase *usecase;
9166 struct listnode *node;
9167 list_for_each(node, &adev->usecase_list) {
9168 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309169 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309170 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device)) && (is_sco_in_device_type(&usecase->stream.in->device_list))) {
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309171 ALOGD("BT_SCO ON, switch all in use case to it");
9172 select_devices(adev, usecase->id);
9173 }
Mingshu Pangef517202021-04-22 10:35:00 +08009174 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9175 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309176 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE)) && (is_sco_out_device_type(&usecase->stream.out->device_list))) {
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309177 ALOGD("BT_SCO ON, switch all out use case to it");
9178 select_devices(adev, usecase->id);
9179 }
9180 }
9181 }
9182 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309183 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009184 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009185 }
9186 }
9187
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009188 status = voice_set_parameters(adev, parms);
9189 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009190 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009191
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009192 status = platform_set_parameters(adev->platform, parms);
9193 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009194 goto done;
9195
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009196 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9197 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009198 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9200 adev->bluetooth_nrec = true;
9201 else
9202 adev->bluetooth_nrec = false;
9203 }
9204
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009205 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9206 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009207 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9208 adev->screen_off = false;
9209 else
9210 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009211 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009212 }
9213
Eric Laurent4b084132018-10-19 17:33:43 -07009214 ret = str_parms_get_int(parms, "rotation", &val);
9215 if (ret >= 0) {
9216 bool reverse_speakers = false;
9217 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9218 switch (val) {
9219 // FIXME: note that the code below assumes that the speakers are in the correct placement
9220 // relative to the user when the device is rotated 90deg from its default rotation. This
9221 // assumption is device-specific, not platform-specific like this code.
9222 case 270:
9223 reverse_speakers = true;
9224 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9225 break;
9226 case 0:
9227 case 180:
9228 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9229 break;
9230 case 90:
9231 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9232 break;
9233 default:
9234 ALOGE("%s: unexpected rotation of %d", __func__, val);
9235 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009236 }
Eric Laurent4b084132018-10-19 17:33:43 -07009237 if (status == 0) {
9238 // check and set swap
9239 // - check if orientation changed and speaker active
9240 // - set rotation and cache the rotation value
9241 adev->camera_orientation =
9242 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9243 if (!audio_extn_is_maxx_audio_enabled())
9244 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9245 }
9246 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009247
Mingming Yin514a8bc2014-07-29 15:22:21 -07009248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9249 if (ret >= 0) {
9250 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9251 adev->bt_wb_speech_enabled = true;
9252 else
9253 adev->bt_wb_speech_enabled = false;
9254 }
9255
Zhou Song12c29502019-03-16 10:37:18 +08009256 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9257 if (ret >= 0) {
9258 val = atoi(value);
9259 adev->swb_speech_mode = val;
9260 }
9261
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9263 if (ret >= 0) {
9264 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309265 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009266 if (audio_is_output_device(val) &&
9267 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009268 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009269 platform_get_controller_stream_from_params(parms, &controller, &stream);
9270 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9271 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009272 if (ret < 0) {
9273 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309274 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009275 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009276 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309277 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009278 /*
9279 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9280 * Per AudioPolicyManager, USB device is higher priority than WFD.
9281 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9282 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9283 * starting voice call on USB
9284 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009285 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309286 if (ret >= 0)
9287 audio_extn_usb_add_device(device, atoi(value));
9288
Zhou Song6f862822017-11-06 17:27:57 +08009289 if (!audio_extn_usb_is_tunnel_supported()) {
9290 ALOGV("detected USB connect .. disable proxy");
9291 adev->allow_afe_proxy_usage = false;
9292 }
Zhou Song503196b2021-07-23 17:31:05 +08009293 } else if (audio_is_hearing_aid_out_device(device) &&
9294 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9295 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009296 }
9297 }
9298
9299 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9300 if (ret >= 0) {
9301 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309302 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009303 /*
9304 * The HDMI / Displayport disconnect handling has been moved to
9305 * audio extension to ensure that its parameters are not
9306 * invalidated prior to updating sysfs of the disconnect event
9307 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9308 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309309 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009310 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309311 if (ret >= 0)
9312 audio_extn_usb_remove_device(device, atoi(value));
9313
Zhou Song6f862822017-11-06 17:27:57 +08009314 if (!audio_extn_usb_is_tunnel_supported()) {
9315 ALOGV("detected USB disconnect .. enable proxy");
9316 adev->allow_afe_proxy_usage = true;
9317 }
Zhou Song503196b2021-07-23 17:31:05 +08009318 } else if (audio_is_hearing_aid_out_device(device)) {
9319 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009320 }
9321 }
9322
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009323 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009324
9325 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009326 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309327 struct audio_usecase *usecase;
9328 struct listnode *node;
9329 list_for_each(node, &adev->usecase_list) {
9330 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009331 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9332 continue;
9333
9334 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309335 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309336 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309337 ALOGD("Switching to speaker and muting the stream before select_devices");
9338 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309339 //force device switch to re configure encoder
9340 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309341 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009342 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309343 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309344 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009345 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009346 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009347 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009348 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9349 reassign_device_list(&usecase->stream.out->device_list,
9350 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9351 check_a2dp_restore_l(adev, usecase->stream.out, true);
9352 break;
9353 }
9354 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309355 }
9356 }
9357 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009358
9359 //handle vr audio setparam
9360 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9361 value, sizeof(value));
9362 if (ret >= 0) {
9363 ALOGI("Setting vr mode to be %s", value);
9364 if (!strncmp(value, "true", 4)) {
9365 adev->vr_audio_mode_enabled = true;
9366 ALOGI("Setting vr mode to true");
9367 } else if (!strncmp(value, "false", 5)) {
9368 adev->vr_audio_mode_enabled = false;
9369 ALOGI("Setting vr mode to false");
9370 } else {
9371 ALOGI("wrong vr mode set");
9372 }
9373 }
9374
Eric Laurent4b084132018-10-19 17:33:43 -07009375 //FIXME: to be replaced by proper video capture properties API
9376 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9377 if (ret >= 0) {
9378 int camera_facing = CAMERA_FACING_BACK;
9379 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9380 camera_facing = CAMERA_FACING_FRONT;
9381 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9382 camera_facing = CAMERA_FACING_BACK;
9383 else {
9384 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9385 goto done;
9386 }
9387 adev->camera_orientation =
9388 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9389 struct audio_usecase *usecase;
9390 struct listnode *node;
9391 list_for_each(node, &adev->usecase_list) {
9392 usecase = node_to_item(node, struct audio_usecase, list);
9393 struct stream_in *in = usecase->stream.in;
9394 if (usecase->type == PCM_CAPTURE && in != NULL &&
9395 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9396 select_devices(adev, in->usecase);
9397 }
9398 }
9399 }
9400
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309401 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009402done:
9403 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009404 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309405error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009406 ALOGV("%s: exit with code(%d)", __func__, status);
9407 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009408}
9409
9410static char* adev_get_parameters(const struct audio_hw_device *dev,
9411 const char *keys)
9412{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309413 ALOGD("%s:%s", __func__, keys);
9414
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009415 struct audio_device *adev = (struct audio_device *)dev;
9416 struct str_parms *reply = str_parms_create();
9417 struct str_parms *query = str_parms_create_str(keys);
9418 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309419 char value[256] = {0};
9420 int ret = 0;
9421
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009422 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009423 if (reply) {
9424 str_parms_destroy(reply);
9425 }
9426 if (query) {
9427 str_parms_destroy(query);
9428 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009429 ALOGE("adev_get_parameters: failed to create query or reply");
9430 return NULL;
9431 }
9432
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009433 //handle vr audio getparam
9434
9435 ret = str_parms_get_str(query,
9436 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9437 value, sizeof(value));
9438
9439 if (ret >= 0) {
9440 bool vr_audio_enabled = false;
9441 pthread_mutex_lock(&adev->lock);
9442 vr_audio_enabled = adev->vr_audio_mode_enabled;
9443 pthread_mutex_unlock(&adev->lock);
9444
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009445 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009446
9447 if (vr_audio_enabled) {
9448 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9449 "true");
9450 goto exit;
9451 } else {
9452 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9453 "false");
9454 goto exit;
9455 }
9456 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009457
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009458 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009459 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009460 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009461 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009462 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009463 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309464 pthread_mutex_unlock(&adev->lock);
9465
Naresh Tannirud7205b62014-06-20 02:54:48 +05309466exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009467 str = str_parms_to_str(reply);
9468 str_parms_destroy(query);
9469 str_parms_destroy(reply);
9470
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009471 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009472 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009473}
9474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009475static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009476{
9477 return 0;
9478}
9479
9480static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9481{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009482 int ret;
9483 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009484
9485 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9486
Haynes Mathew George5191a852013-09-11 14:19:36 -07009487 pthread_mutex_lock(&adev->lock);
9488 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009489 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009490 pthread_mutex_unlock(&adev->lock);
9491 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009492}
9493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009494static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9495 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009496{
9497 return -ENOSYS;
9498}
9499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009500static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9501 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009502{
9503 return -ENOSYS;
9504}
9505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009506static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9507 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009508{
9509 return -ENOSYS;
9510}
9511
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009512static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9513 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009514{
9515 return -ENOSYS;
9516}
9517
9518static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9519{
9520 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009521 struct listnode *node;
9522 struct audio_usecase *usecase = NULL;
9523 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009525 pthread_mutex_lock(&adev->lock);
9526 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309527 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9528 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009529 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009530 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309531 adev->current_call_output = adev->primary_output;
9532 voice_start_call(adev);
9533 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009534 (mode == AUDIO_MODE_NORMAL ||
9535 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009536 list_for_each(node, &adev->usecase_list) {
9537 usecase = node_to_item(node, struct audio_usecase, list);
9538 if (usecase->type == VOICE_CALL)
9539 break;
9540 }
9541 if (usecase &&
9542 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9543 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9544 true);
9545 if (ret != 0) {
9546 /* default service interval was successfully updated,
9547 reopen USB backend with new service interval */
9548 check_usecases_codec_backend(adev,
9549 usecase,
9550 usecase->out_snd_device);
9551 }
9552 }
9553
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009554 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009555 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009556 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009557 // restore device for other active usecases after stop call
9558 list_for_each(node, &adev->usecase_list) {
9559 usecase = node_to_item(node, struct audio_usecase, list);
9560 select_devices(adev, usecase->id);
9561 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009563 }
9564 pthread_mutex_unlock(&adev->lock);
9565 return 0;
9566}
9567
9568static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9569{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009570 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009571 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009572
9573 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009574 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009575 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009576
Derek Chend2530072014-11-24 12:39:14 -08009577 if (adev->ext_hw_plugin)
9578 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009579
9580 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009581 pthread_mutex_unlock(&adev->lock);
9582
9583 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009584}
9585
9586static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9587{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009588 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009589 return 0;
9590}
9591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009592static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009593 const struct audio_config *config)
9594{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009595 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009596
Aalique Grahame22e49102018-12-18 14:23:57 -08009597 /* Don't know if USB HIFI in this context so use true to be conservative */
9598 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9599 true /*is_usb_hifi */) != 0)
9600 return 0;
9601
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009602 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9603 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009604}
9605
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009606static bool adev_input_allow_hifi_record(struct audio_device *adev,
9607 audio_devices_t devices,
9608 audio_input_flags_t flags,
9609 audio_source_t source) {
9610 const bool allowed = true;
9611
9612 if (!audio_is_usb_in_device(devices))
9613 return !allowed;
9614
9615 switch (flags) {
9616 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009617 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009618 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9619 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009620 default:
9621 return !allowed;
9622 }
9623
9624 switch (source) {
9625 case AUDIO_SOURCE_DEFAULT:
9626 case AUDIO_SOURCE_MIC:
9627 case AUDIO_SOURCE_UNPROCESSED:
9628 break;
9629 default:
9630 return !allowed;
9631 }
9632
9633 switch (adev->mode) {
9634 case 0:
9635 break;
9636 default:
9637 return !allowed;
9638 }
9639
9640 return allowed;
9641}
9642
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009643static int adev_update_voice_comm_input_stream(struct stream_in *in,
9644 struct audio_config *config)
9645{
9646 bool valid_rate = (config->sample_rate == 8000 ||
9647 config->sample_rate == 16000 ||
9648 config->sample_rate == 32000 ||
9649 config->sample_rate == 48000);
9650 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9651
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009652 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009653 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009654 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9655 in->config = default_pcm_config_voip_copp;
9656 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9657 DEFAULT_VOIP_BUF_DURATION_MS,
9658 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009659 } else {
9660 ALOGW("%s No valid input in voip, use defaults"
9661 "sample rate %u, channel mask 0x%X",
9662 __func__, config->sample_rate, in->channel_mask);
9663 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009664 in->config.rate = config->sample_rate;
9665 in->sample_rate = config->sample_rate;
9666 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009667 //XXX needed for voice_extn_compress_voip_open_input_stream
9668 in->config.rate = config->sample_rate;
9669 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309670 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009671 voice_extn_compress_voip_is_active(in->dev)) &&
9672 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9673 valid_rate && valid_ch) {
9674 voice_extn_compress_voip_open_input_stream(in);
9675 // update rate entries to match config from AF
9676 in->config.rate = config->sample_rate;
9677 in->sample_rate = config->sample_rate;
9678 } else {
9679 ALOGW("%s compress voip not active, use defaults", __func__);
9680 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009681 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009682 return 0;
9683}
9684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009685static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009686 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009687 audio_devices_t devices,
9688 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009689 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309690 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009691 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009692 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009693{
9694 struct audio_device *adev = (struct audio_device *)dev;
9695 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009696 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009697 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009698 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309699 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009700 bool is_usb_dev = audio_is_usb_in_device(devices);
9701 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9702 devices,
9703 flags,
9704 source);
Andy Hung94320602018-10-29 18:31:12 -07009705 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9706 " sample_rate %u, channel_mask %#x, format %#x",
9707 __func__, flags, is_usb_dev, may_use_hifi_record,
9708 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309709
kunleizdff872d2018-08-20 14:40:33 +08009710 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009711 is_usb_dev = false;
9712 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9713 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9714 __func__, devices);
9715 }
9716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009717 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009718
9719 if (!(is_usb_dev && may_use_hifi_record)) {
9720 if (config->sample_rate == 0)
9721 config->sample_rate = 48000;
9722 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9723 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9724 if (config->format == AUDIO_FORMAT_DEFAULT)
9725 config->format = AUDIO_FORMAT_PCM_16_BIT;
9726
9727 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9728
Aalique Grahame22e49102018-12-18 14:23:57 -08009729 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9730 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009731 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309732 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009733
9734 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009735
9736 if (!in) {
9737 ALOGE("failed to allocate input stream");
9738 return -ENOMEM;
9739 }
9740
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309741 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309742 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9743 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009744 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009745 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009747 in->stream.common.get_sample_rate = in_get_sample_rate;
9748 in->stream.common.set_sample_rate = in_set_sample_rate;
9749 in->stream.common.get_buffer_size = in_get_buffer_size;
9750 in->stream.common.get_channels = in_get_channels;
9751 in->stream.common.get_format = in_get_format;
9752 in->stream.common.set_format = in_set_format;
9753 in->stream.common.standby = in_standby;
9754 in->stream.common.dump = in_dump;
9755 in->stream.common.set_parameters = in_set_parameters;
9756 in->stream.common.get_parameters = in_get_parameters;
9757 in->stream.common.add_audio_effect = in_add_audio_effect;
9758 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9759 in->stream.set_gain = in_set_gain;
9760 in->stream.read = in_read;
9761 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009762 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309763 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009764 in->stream.set_microphone_direction = in_set_microphone_direction;
9765 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009766 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009767
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009768 list_init(&in->device_list);
9769 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009770 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009771 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009772 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009773 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009774 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009775 in->bit_width = 16;
9776 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009777 in->direction = MIC_DIRECTION_UNSPECIFIED;
9778 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009779 list_init(&in->aec_list);
9780 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009781 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009782
Andy Hung94320602018-10-29 18:31:12 -07009783 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009784 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9785 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9786 /* Force channel config requested to mono if incall
9787 record is being requested for only uplink/downlink */
9788 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9789 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9790 ret = -EINVAL;
9791 goto err_open;
9792 }
9793 }
9794
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009795 if (is_usb_dev && may_use_hifi_record) {
9796 /* HiFi record selects an appropriate format, channel, rate combo
9797 depending on sink capabilities*/
9798 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9799 &config->format,
9800 &in->supported_formats[0],
9801 MAX_SUPPORTED_FORMATS,
9802 &config->channel_mask,
9803 &in->supported_channel_masks[0],
9804 MAX_SUPPORTED_CHANNEL_MASKS,
9805 &config->sample_rate,
9806 &in->supported_sample_rates[0],
9807 MAX_SUPPORTED_SAMPLE_RATES);
9808 if (ret != 0) {
9809 ret = -EINVAL;
9810 goto err_open;
9811 }
9812 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009813 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309814 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309815 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9816 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9817 in->config.format = PCM_FORMAT_S32_LE;
9818 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309819 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9820 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9821 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9822 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9823 bool ret_error = false;
9824 in->bit_width = 24;
9825 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9826 from HAL is 24_packed and 8_24
9827 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9828 24_packed return error indicating supported format is 24_packed
9829 *> In case of any other source requesting 24 bit or float return error
9830 indicating format supported is 16 bit only.
9831
9832 on error flinger will retry with supported format passed
9833 */
9834 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9835 (source != AUDIO_SOURCE_CAMCORDER)) {
9836 config->format = AUDIO_FORMAT_PCM_16_BIT;
9837 if (config->sample_rate > 48000)
9838 config->sample_rate = 48000;
9839 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009840 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9841 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309842 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9843 ret_error = true;
9844 }
9845
9846 if (ret_error) {
9847 ret = -EINVAL;
9848 goto err_open;
9849 }
9850 }
9851
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009852 in->channel_mask = config->channel_mask;
9853 in->format = config->format;
9854
9855 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309856
Huicheng Liu1404ba12020-09-11 01:03:25 -04009857 /* validate bus device address */
9858 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9859 /* extract car audio stream index */
9860 in->car_audio_stream =
9861 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9862 if (in->car_audio_stream < 0) {
9863 ALOGE("%s: invalid car audio stream %x",
9864 __func__, in->car_audio_stream);
9865 ret = -EINVAL;
9866 goto err_open;
9867 }
9868 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009869 ret = audio_extn_auto_hal_open_input_stream(in);
9870 if (ret) {
9871 ALOGE("%s: Failed to open input stream for bus device", __func__);
9872 ret = -EINVAL;
9873 goto err_open;
9874 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009875 }
9876
Susan Wange3959562021-03-11 11:50:26 -05009877 /* reassign use case for echo reference stream on automotive platforms */
9878 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9879 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9880 }
9881
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309882 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309883 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9884 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9885 else {
9886 ret = -EINVAL;
9887 goto err_open;
9888 }
9889 }
9890
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309891 if ((config->sample_rate == 48000 ||
9892 config->sample_rate == 32000 ||
9893 config->sample_rate == 24000 ||
9894 config->sample_rate == 16000 ||
9895 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309896 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9897 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009898 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9899 is_low_latency = true;
9900#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309901 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9902 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9903 else
9904 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009905#endif
9906 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009907 if (!in->realtime) {
9908 in->config = pcm_config_audio_capture;
9909 frame_size = audio_stream_in_frame_size(&in->stream);
9910 buffer_size = get_input_buffer_size(config->sample_rate,
9911 config->format,
9912 channel_count,
9913 is_low_latency);
9914 in->config.period_size = buffer_size / frame_size;
9915 in->config.rate = config->sample_rate;
9916 in->af_period_multiplier = 1;
9917 } else {
9918 // period size is left untouched for rt mode playback
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309919 switch(config->sample_rate)
9920 {
9921 case 48000:
9922 in->config = pcm_config_audio_capture_rt_48KHz;
9923 break;
9924 case 32000:
9925 in->config = pcm_config_audio_capture_rt_32KHz;
9926 break;
9927 case 24000:
9928 in->config = pcm_config_audio_capture_rt_24KHz;
9929 break;
9930 case 16000:
9931 in->config = pcm_config_audio_capture_rt_16KHz;
9932 break;
9933 case 8000:
9934 in->config = pcm_config_audio_capture_rt_8KHz;
9935 break;
9936 default:
9937 in->config = pcm_config_audio_capture_rt_48KHz;
9938 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009939 in->af_period_multiplier = af_period_multiplier;
9940 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009941 }
9942
Susan Wangb803cb52021-10-14 12:03:36 -04009943 /* Additional sample rates added below must also be present
9944 in audio_policy_configuration.xml for mmap_no_irq_in */
9945 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9946 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009947 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009948 config->sample_rate == 32000 ||
9949 config->sample_rate == 48000);
9950 if (valid_mmap_record_rate &&
9951 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009952 in->realtime = 0;
9953 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9954 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009955 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009956 in->stream.start = in_start;
9957 in->stream.stop = in_stop;
9958 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9959 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309960 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009961 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009962 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009963 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9964 in->config = pcm_config_audio_capture;
9965 frame_size = audio_stream_in_frame_size(&in->stream);
9966 buffer_size = get_input_buffer_size(config->sample_rate,
9967 config->format,
9968 channel_count,
9969 false /*is_low_latency*/);
9970 in->config.period_size = buffer_size / frame_size;
9971 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009972 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009973 switch (config->format) {
9974 case AUDIO_FORMAT_PCM_32_BIT:
9975 in->bit_width = 32;
9976 break;
9977 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9978 case AUDIO_FORMAT_PCM_8_24_BIT:
9979 in->bit_width = 24;
9980 break;
9981 default:
9982 in->bit_width = 16;
9983 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009984 } else if (is_single_device_type_equal(&in->device_list,
9985 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9986 is_single_device_type_equal(&in->device_list,
9987 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009988 if (config->sample_rate == 0)
9989 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9990 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9991 config->sample_rate != 8000) {
9992 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9993 ret = -EINVAL;
9994 goto err_open;
9995 }
9996 if (config->format == AUDIO_FORMAT_DEFAULT)
9997 config->format = AUDIO_FORMAT_PCM_16_BIT;
9998 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9999 config->format = AUDIO_FORMAT_PCM_16_BIT;
10000 ret = -EINVAL;
10001 goto err_open;
10002 }
10003
10004 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010005 if (adev->ha_proxy_enable &&
10006 is_single_device_type_equal(&in->device_list,
10007 AUDIO_DEVICE_IN_TELEPHONY_RX))
10008 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010009 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010010 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010011 in->af_period_multiplier = 1;
10012 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010013 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010014 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10015 (config->sample_rate == 8000 ||
10016 config->sample_rate == 16000 ||
10017 config->sample_rate == 32000 ||
10018 config->sample_rate == 48000) &&
10019 channel_count == 1) {
10020 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10021 in->config = pcm_config_audio_capture;
10022 frame_size = audio_stream_in_frame_size(&in->stream);
10023 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10024 config->sample_rate,
10025 config->format,
10026 channel_count, false /*is_low_latency*/);
10027 in->config.period_size = buffer_size / frame_size;
10028 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10029 in->config.rate = config->sample_rate;
10030 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010031 } else if (in->realtime) {
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010032 switch(config->sample_rate)
10033 {
10034 case 48000:
10035 in->config = pcm_config_audio_capture_rt_48KHz;
10036 break;
10037 case 32000:
10038 in->config = pcm_config_audio_capture_rt_32KHz;
10039 break;
10040 case 24000:
10041 in->config = pcm_config_audio_capture_rt_24KHz;
10042 break;
10043 case 16000:
10044 in->config = pcm_config_audio_capture_rt_16KHz;
10045 break;
10046 case 8000:
10047 in->config = pcm_config_audio_capture_rt_8KHz;
10048 break;
10049 default:
10050 in->config = pcm_config_audio_capture_rt_48KHz;
10051 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010052 in->config.format = pcm_format_from_audio_format(config->format);
10053 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -070010054 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010055 int ret_val;
10056 pthread_mutex_lock(&adev->lock);
10057 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10058 in, config, &channel_mask_updated);
10059 pthread_mutex_unlock(&adev->lock);
10060
10061 if (!ret_val) {
10062 if (channel_mask_updated == true) {
10063 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10064 __func__, config->channel_mask);
10065 ret = -EINVAL;
10066 goto err_open;
10067 }
10068 ALOGD("%s: created multi-channel session succesfully",__func__);
10069 } else if (audio_extn_compr_cap_enabled() &&
10070 audio_extn_compr_cap_format_supported(config->format) &&
10071 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10072 audio_extn_compr_cap_init(in);
10073 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010074 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010075 if (ret)
10076 goto err_open;
10077 } else {
10078 in->config = pcm_config_audio_capture;
10079 in->config.rate = config->sample_rate;
10080 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010081 in->format = config->format;
10082 frame_size = audio_stream_in_frame_size(&in->stream);
10083 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010084 config->format,
10085 channel_count,
10086 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010087 /* prevent division-by-zero */
10088 if (frame_size == 0) {
10089 ALOGE("%s: Error frame_size==0", __func__);
10090 ret = -EINVAL;
10091 goto err_open;
10092 }
10093
Revathi Uddarajud2634032017-12-07 14:42:34 +053010094 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010095 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010096
Revathi Uddarajud2634032017-12-07 14:42:34 +053010097 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10098 /* optionally use VOIP usecase depending on config(s) */
10099 ret = adev_update_voice_comm_input_stream(in, config);
10100 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010101
Revathi Uddarajud2634032017-12-07 14:42:34 +053010102 if (ret) {
10103 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10104 goto err_open;
10105 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010106 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010107
10108 /* assign concurrent capture usecase if record has to caried out from
10109 * actual hardware input source */
10110 if (audio_extn_is_concurrent_capture_enabled() &&
10111 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010112 /* Acquire lock to avoid two concurrent use cases initialized to
10113 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010114
Samyak Jainc37062f2019-04-25 18:41:06 +053010115 if (in->usecase == USECASE_AUDIO_RECORD) {
10116 pthread_mutex_lock(&adev->lock);
10117 if (!(adev->pcm_record_uc_state)) {
10118 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10119 adev->pcm_record_uc_state = 1;
10120 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010121 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10122 in->usecase = get_record_usecase(adev);
10123 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010124 } else {
10125 pthread_mutex_unlock(&adev->lock);
10126 /* Assign compress record use case for second record */
10127 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10128 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10129 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10130 if (audio_extn_cin_applicable_stream(in)) {
10131 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010132 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010133 if (ret)
10134 goto err_open;
10135 }
10136 }
10137 }
kunleiz28c73e72019-03-27 17:24:04 +080010138 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010139 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010140
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010141 if (audio_extn_ssr_get_stream() != in)
10142 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010143
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010144 in->sample_rate = in->config.rate;
10145
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010146 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10147 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010148 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010149 in->sample_rate, in->bit_width,
10150 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010151 register_format(in->format, in->supported_formats);
10152 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10153 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010154
Dechen Chai22768452021-07-30 09:29:16 +053010155#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010156 in->error_log = error_log_create(
10157 ERROR_LOG_ENTRIES,
10158 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010159#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010160
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010161 /* This stream could be for sound trigger lab,
10162 get sound trigger pcm if present */
10163 audio_extn_sound_trigger_check_and_get_session(in);
10164
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010165 lock_input_stream(in);
10166 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10167 pthread_mutex_lock(&adev->lock);
10168 in->card_status = adev->card_status;
10169 pthread_mutex_unlock(&adev->lock);
10170 pthread_mutex_unlock(&in->lock);
10171
Aalique Grahame22e49102018-12-18 14:23:57 -080010172 stream_app_type_cfg_init(&in->app_type_cfg);
10173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010174 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010175
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010176 ret = io_streams_map_insert(adev, &in->stream.common,
10177 handle, AUDIO_PATCH_HANDLE_NONE);
10178 if (ret != 0)
10179 goto err_open;
10180
Susan Wang6dd13092021-01-25 10:27:11 -050010181 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010182
10183 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010184 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010185 pthread_mutex_unlock(&adev->lock);
10186
Eric Laurent994a6932013-07-17 11:51:42 -070010187 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010189
10190err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010191 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10192 free_record_usecase(adev, in->usecase);
10193 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010194 pthread_mutex_lock(&adev->lock);
10195 adev->pcm_record_uc_state = 0;
10196 pthread_mutex_unlock(&adev->lock);
10197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010198 free(in);
10199 *stream_in = NULL;
10200 return ret;
10201}
10202
10203static void adev_close_input_stream(struct audio_hw_device *dev,
10204 struct audio_stream_in *stream)
10205{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010206 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010207 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010208 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010209
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010210 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010211
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010212 if (in == NULL) {
10213 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10214 return;
10215 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010216 io_streams_map_remove(adev, in->capture_handle);
10217
Susan Wang6dd13092021-01-25 10:27:11 -050010218 // remove out_ctxt early to prevent the stream
10219 // being opened in a race condition
10220 pthread_mutex_lock(&adev->lock);
10221 list_remove(&in->in_ctxt.list);
10222 pthread_mutex_unlock(&adev->lock);
10223
kunleiz70e57612018-12-28 17:50:23 +080010224 /* must deregister from sndmonitor first to prevent races
10225 * between the callback and close_stream
10226 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010227 audio_extn_snd_mon_unregister_listener(stream);
10228
kunleiz70e57612018-12-28 17:50:23 +080010229 /* Disable echo reference if there are no active input, hfp call
10230 * and sound trigger while closing input stream
10231 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010232 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010233 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010234 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10235 struct listnode out_devices;
10236 list_init(&out_devices);
10237 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010238 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010239 } else
kunleiz70e57612018-12-28 17:50:23 +080010240 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010241
Dechen Chai22768452021-07-30 09:29:16 +053010242#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010243 error_log_destroy(in->error_log);
10244 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010245#endif
Pallavid7c7a272018-01-16 11:22:55 +053010246
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010247 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010248 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010249 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010250 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010251 if (ret != 0)
10252 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10253 __func__, ret);
10254 } else
10255 in_standby(&stream->common);
10256
Weiyin Jiang280ea742020-09-08 20:28:22 +080010257 pthread_mutex_destroy(&in->lock);
10258 pthread_mutex_destroy(&in->pre_lock);
10259
Revathi Uddarajud2634032017-12-07 14:42:34 +053010260 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010261 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10262 free_record_usecase(adev, in->usecase);
10263 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010264 adev->pcm_record_uc_state = 0;
10265 }
10266
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010267 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10268 adev->enable_voicerx = false;
10269 }
10270
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010271 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010272 audio_extn_ssr_deinit();
10273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010274
Garmond Leunge2433c32017-09-28 21:51:22 -070010275 if (audio_extn_ffv_get_stream() == in) {
10276 audio_extn_ffv_stream_deinit();
10277 }
10278
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010279 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -070010280 audio_extn_compr_cap_format_supported(in->config.format))
10281 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010282
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010283 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010284 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010285
Mingming Yinfd7607b2016-01-22 12:48:44 -080010286 if (in->is_st_session) {
10287 ALOGV("%s: sound trigger pcm stop lab", __func__);
10288 audio_extn_sound_trigger_stop_lab(in);
10289 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010290 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010291 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010292 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010293 return;
10294}
10295
Aalique Grahame22e49102018-12-18 14:23:57 -080010296/* verifies input and output devices and their capabilities.
10297 *
10298 * This verification is required when enabling extended bit-depth or
10299 * sampling rates, as not all qcom products support it.
10300 *
10301 * Suitable for calling only on initialization such as adev_open().
10302 * It fills the audio_device use_case_table[] array.
10303 *
10304 * Has a side-effect that it needs to configure audio routing / devices
10305 * in order to power up the devices and read the device parameters.
10306 * It does not acquire any hw device lock. Should restore the devices
10307 * back to "normal state" upon completion.
10308 */
10309static int adev_verify_devices(struct audio_device *adev)
10310{
10311 /* enumeration is a bit difficult because one really wants to pull
10312 * the use_case, device id, etc from the hidden pcm_device_table[].
10313 * In this case there are the following use cases and device ids.
10314 *
10315 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10316 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10317 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10318 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10319 * [USECASE_AUDIO_RECORD] = {0, 0},
10320 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10321 * [USECASE_VOICE_CALL] = {2, 2},
10322 *
10323 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10324 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10325 */
10326
10327 /* should be the usecases enabled in adev_open_input_stream() */
10328 static const int test_in_usecases[] = {
10329 USECASE_AUDIO_RECORD,
10330 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10331 };
10332 /* should be the usecases enabled in adev_open_output_stream()*/
10333 static const int test_out_usecases[] = {
10334 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10335 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10336 };
10337 static const usecase_type_t usecase_type_by_dir[] = {
10338 PCM_PLAYBACK,
10339 PCM_CAPTURE,
10340 };
10341 static const unsigned flags_by_dir[] = {
10342 PCM_OUT,
10343 PCM_IN,
10344 };
10345
10346 size_t i;
10347 unsigned dir;
10348 const unsigned card_id = adev->snd_card;
10349
10350 for (dir = 0; dir < 2; ++dir) {
10351 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10352 const unsigned flags_dir = flags_by_dir[dir];
10353 const size_t testsize =
10354 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10355 const int *testcases =
10356 dir ? test_in_usecases : test_out_usecases;
10357 const audio_devices_t audio_device =
10358 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10359
10360 for (i = 0; i < testsize; ++i) {
10361 const audio_usecase_t audio_usecase = testcases[i];
10362 int device_id;
10363 struct pcm_params **pparams;
10364 struct stream_out out;
10365 struct stream_in in;
10366 struct audio_usecase uc_info;
10367 int retval;
10368
10369 pparams = &adev->use_case_table[audio_usecase];
10370 pcm_params_free(*pparams); /* can accept null input */
10371 *pparams = NULL;
10372
10373 /* find the device ID for the use case (signed, for error) */
10374 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10375 if (device_id < 0)
10376 continue;
10377
10378 /* prepare structures for device probing */
10379 memset(&uc_info, 0, sizeof(uc_info));
10380 uc_info.id = audio_usecase;
10381 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010382 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010383 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010384 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010385 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010386 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010387 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10388 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010389 }
10390 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010391 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010392 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010393 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010394 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010395 uc_info.in_snd_device = SND_DEVICE_NONE;
10396 uc_info.out_snd_device = SND_DEVICE_NONE;
10397 list_add_tail(&adev->usecase_list, &uc_info.list);
10398
10399 /* select device - similar to start_(in/out)put_stream() */
10400 retval = select_devices(adev, audio_usecase);
10401 if (retval >= 0) {
10402 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10403#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010404 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010405 if (*pparams) {
10406 ALOGV("%s: (%s) card %d device %d", __func__,
10407 dir ? "input" : "output", card_id, device_id);
10408 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10409 } else {
10410 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10411 }
10412#endif
10413 }
10414
10415 /* deselect device - similar to stop_(in/out)put_stream() */
10416 /* 1. Get and set stream specific mixer controls */
10417 retval = disable_audio_route(adev, &uc_info);
10418 /* 2. Disable the rx device */
10419 retval = disable_snd_device(adev,
10420 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10421 list_remove(&uc_info.list);
10422 }
10423 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010424 return 0;
10425}
10426
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010427int update_patch(unsigned int num_sources,
10428 const struct audio_port_config *sources,
10429 unsigned int num_sinks,
10430 const struct audio_port_config *sinks,
10431 audio_patch_handle_t handle,
10432 struct audio_patch_info *p_info,
10433 patch_type_t patch_type, bool new_patch)
10434{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010435 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010436
10437 if (p_info == NULL) {
10438 ALOGE("%s: Invalid patch pointer", __func__);
10439 return -EINVAL;
10440 }
10441
10442 if (new_patch) {
10443 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10444 if (p_info->patch == NULL) {
10445 ALOGE("%s: Could not allocate patch", __func__);
10446 return -ENOMEM;
10447 }
10448 }
10449
10450 p_info->patch->id = handle;
10451 p_info->patch->num_sources = num_sources;
10452 p_info->patch->num_sinks = num_sinks;
10453
10454 for (int i = 0; i < num_sources; i++)
10455 p_info->patch->sources[i] = sources[i];
10456 for (int i = 0; i < num_sinks; i++)
10457 p_info->patch->sinks[i] = sinks[i];
10458
10459 p_info->patch_type = patch_type;
10460 return 0;
10461}
10462
10463audio_patch_handle_t generate_patch_handle()
10464{
10465 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10466 if (++patch_handle < 0)
10467 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10468 return patch_handle;
10469}
10470
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010471int adev_create_audio_patch(struct audio_hw_device *dev,
10472 unsigned int num_sources,
10473 const struct audio_port_config *sources,
10474 unsigned int num_sinks,
10475 const struct audio_port_config *sinks,
10476 audio_patch_handle_t *handle)
10477{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010478 int ret = 0;
10479 struct audio_device *adev = (struct audio_device *)dev;
10480 struct audio_patch_info *p_info = NULL;
10481 patch_type_t patch_type = PATCH_NONE;
10482 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10483 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10484 struct audio_stream_info *s_info = NULL;
10485 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010486 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010487 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10488 bool new_patch = false;
10489 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010490
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010491 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10492 num_sources, num_sinks, *handle);
10493
10494 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10495 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10496 ALOGE("%s: Invalid patch arguments", __func__);
10497 ret = -EINVAL;
10498 goto done;
10499 }
10500
10501 if (num_sources > 1) {
10502 ALOGE("%s: Multiple sources are not supported", __func__);
10503 ret = -EINVAL;
10504 goto done;
10505 }
10506
10507 if (sources == NULL || sinks == NULL) {
10508 ALOGE("%s: Invalid sources or sinks port config", __func__);
10509 ret = -EINVAL;
10510 goto done;
10511 }
10512
10513 ALOGV("%s: source role %d, source type %d", __func__,
10514 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010515 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010516
10517 // Populate source/sink information and fetch stream info
10518 switch (sources[0].type) {
10519 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10520 device_type = sources[0].ext.device.type;
10521 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010522 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010523 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10524 patch_type = PATCH_CAPTURE;
10525 io_handle = sinks[0].ext.mix.handle;
10526 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010527 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010528 __func__, device_type, io_handle);
10529 } else {
10530 // Device to device patch is not implemented.
10531 // This space will need changes if audio HAL
10532 // handles device to device patches in the future.
10533 patch_type = PATCH_DEVICE_LOOPBACK;
10534 }
10535 break;
10536 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10537 io_handle = sources[0].ext.mix.handle;
10538 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010539 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010540 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010541 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010542 }
10543 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010544 ALOGD("%s: Playback patch from mix handle %d to device %x",
10545 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010546 break;
10547 case AUDIO_PORT_TYPE_SESSION:
10548 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010549 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10550 ret = -EINVAL;
10551 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010552 }
10553
10554 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010555
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010556 // Generate patch info and update patch
10557 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010558 *handle = generate_patch_handle();
10559 p_info = (struct audio_patch_info *)
10560 calloc(1, sizeof(struct audio_patch_info));
10561 if (p_info == NULL) {
10562 ALOGE("%s: Failed to allocate memory", __func__);
10563 pthread_mutex_unlock(&adev->lock);
10564 ret = -ENOMEM;
10565 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010566 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010567 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010568 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010569 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010570 if (p_info == NULL) {
10571 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10572 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010573 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010574 ret = -EINVAL;
10575 goto done;
10576 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010577 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010578 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010579 *handle, p_info, patch_type, new_patch);
10580
10581 // Fetch stream info of associated mix for playback or capture patches
10582 if (p_info->patch_type == PATCH_PLAYBACK ||
10583 p_info->patch_type == PATCH_CAPTURE) {
10584 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10585 if (s_info == NULL) {
10586 ALOGE("%s: Failed to obtain stream info", __func__);
10587 if (new_patch)
10588 free(p_info);
10589 pthread_mutex_unlock(&adev->lock);
10590 ret = -EINVAL;
10591 goto done;
10592 }
10593 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10594 s_info->patch_handle = *handle;
10595 stream = s_info->stream;
10596 }
10597 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010598
10599 // Update routing for stream
10600 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010601 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010602 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010603 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010604 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010605 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010606 if (ret < 0) {
10607 pthread_mutex_lock(&adev->lock);
10608 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10609 if (new_patch)
10610 free(p_info);
10611 pthread_mutex_unlock(&adev->lock);
10612 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10613 goto done;
10614 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010615 }
10616
10617 // Add new patch to patch map
10618 if (!ret && new_patch) {
10619 pthread_mutex_lock(&adev->lock);
10620 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010621 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010622 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010623 }
10624
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010625done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010626 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010627 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010628 num_sources,
10629 sources,
10630 num_sinks,
10631 sinks,
10632 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010633 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010634 num_sources,
10635 sources,
10636 num_sinks,
10637 sinks,
10638 handle);
10639 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010640}
10641
10642int adev_release_audio_patch(struct audio_hw_device *dev,
10643 audio_patch_handle_t handle)
10644{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010645 struct audio_device *adev = (struct audio_device *) dev;
10646 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010647 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010648 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010649
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010650 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10651 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10652 ret = -EINVAL;
10653 goto done;
10654 }
10655
10656 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010657 pthread_mutex_lock(&adev->lock);
10658 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010659 if (p_info == NULL) {
10660 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010661 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010662 ret = -EINVAL;
10663 goto done;
10664 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010665 struct audio_patch *patch = p_info->patch;
10666 if (patch == NULL) {
10667 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010668 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010669 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010670 goto done;
10671 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010672 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10673 switch (patch->sources[0].type) {
10674 case AUDIO_PORT_TYPE_MIX:
10675 io_handle = patch->sources[0].ext.mix.handle;
10676 break;
10677 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010678 if (p_info->patch_type == PATCH_CAPTURE)
10679 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010680 break;
10681 case AUDIO_PORT_TYPE_SESSION:
10682 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010683 pthread_mutex_unlock(&adev->lock);
10684 ret = -EINVAL;
10685 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010686 }
10687
10688 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010689 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010690 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010691 if (patch_type == PATCH_PLAYBACK ||
10692 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010693 struct audio_stream_info *s_info =
10694 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10695 if (s_info == NULL) {
10696 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10697 pthread_mutex_unlock(&adev->lock);
10698 goto done;
10699 }
10700 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10701 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010702 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010703 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010704
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010705 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010706 struct listnode devices;
10707 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010708 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010709 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010710 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010711 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010712 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010713 }
10714
10715 if (ret < 0)
10716 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10717
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010718done:
10719 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10720 audio_extn_auto_hal_release_audio_patch(dev, handle);
10721
10722 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010723 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010724}
10725
10726int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10727{
Derek Chenf13dd492018-11-13 14:53:51 -080010728 int ret = 0;
10729
10730 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10731 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10732 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010733}
10734
10735int adev_set_audio_port_config(struct audio_hw_device *dev,
10736 const struct audio_port_config *config)
10737{
Derek Chenf13dd492018-11-13 14:53:51 -080010738 int ret = 0;
10739
10740 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10741 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10742 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010743}
10744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010745static int adev_dump(const audio_hw_device_t *device __unused,
10746 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010747{
10748 return 0;
10749}
10750
10751static int adev_close(hw_device_t *device)
10752{
Aalique Grahame22e49102018-12-18 14:23:57 -080010753 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010754 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010755
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010756 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010757 return 0;
10758
10759 pthread_mutex_lock(&adev_init_lock);
10760
10761 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010762 if (audio_extn_spkr_prot_is_enabled())
10763 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010764 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010765 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010766 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010767 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010768 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010769 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010770 audio_extn_utils_release_streams_cfg_lists(
10771 &adev->streams_output_cfg_list,
10772 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010773 if (audio_extn_qap_is_enabled())
10774 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010775 if (audio_extn_qaf_is_enabled())
10776 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010777 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010778 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010779 free(adev->snd_dev_ref_cnt);
10780 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010781 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10782 pcm_params_free(adev->use_case_table[i]);
10783 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010784 if (adev->adm_deinit)
10785 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010786 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010787 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010788 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010789 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010790 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010791 if (adev->device_cfg_params) {
10792 free(adev->device_cfg_params);
10793 adev->device_cfg_params = NULL;
10794 }
Derek Chend2530072014-11-24 12:39:14 -080010795 if(adev->ext_hw_plugin)
10796 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010797 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010798 free_map(adev->patch_map);
10799 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010800 free(device);
10801 adev = NULL;
10802 }
10803 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010804 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010805 return 0;
10806}
10807
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010808/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10809 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10810 * just that it _might_ work.
10811 */
10812static int period_size_is_plausible_for_low_latency(int period_size)
10813{
10814 switch (period_size) {
10815 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010816 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010817 case 240:
10818 case 320:
10819 case 480:
10820 return 1;
10821 default:
10822 return 0;
10823 }
10824}
10825
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010826static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10827{
10828 bool is_snd_card_status = false;
10829 bool is_ext_device_status = false;
10830 char value[32];
10831 int card = -1;
10832 card_status_t status;
10833
10834 if (cookie != adev || !parms)
10835 return;
10836
10837 if (!parse_snd_card_status(parms, &card, &status)) {
10838 is_snd_card_status = true;
10839 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10840 is_ext_device_status = true;
10841 } else {
10842 // not a valid event
10843 return;
10844 }
10845
10846 pthread_mutex_lock(&adev->lock);
10847 if (card == adev->snd_card || is_ext_device_status) {
10848 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010849 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010850 adev->card_status = status;
10851 platform_snd_card_update(adev->platform, status);
10852 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010853 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010854 if (status == CARD_STATUS_OFFLINE)
10855 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010856 } else if (is_ext_device_status) {
10857 platform_set_parameters(adev->platform, parms);
10858 }
10859 }
10860 pthread_mutex_unlock(&adev->lock);
10861 return;
10862}
10863
Weiyin Jiang280ea742020-09-08 20:28:22 +080010864/* adev lock held */
10865int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010866{
10867 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010868 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010869 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010870 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010871
10872 uc_info = get_usecase_from_list(adev, out->usecase);
10873 if (uc_info == NULL) {
10874 ALOGE("%s: Could not find the usecase (%d) in the list",
10875 __func__, out->usecase);
10876 return -EINVAL;
10877 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010878 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010879
Zhou Songbaddf9f2020-11-20 13:57:39 +080010880 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10881 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010882
10883 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010884 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010885 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010886 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010887 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010888 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10889 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010890
10891 if (is_offload_usecase(out->usecase)) {
10892 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010893 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010894 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10895 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10896 } else {
10897 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010898 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010899 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010900 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010901 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010902 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010903 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010904 // mute stream and switch to speaker if suspended
10905 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010906 assign_devices(&devices, &out->device_list);
10907 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010908 list_for_each(node, &adev->usecase_list) {
10909 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010910 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10911 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010912 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010913 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10914 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010915 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10916 break;
10917 }
10918 }
Zhou Songcf77af02021-05-14 18:21:14 +080010919 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10920 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010921 out->a2dp_muted = true;
10922 if (is_offload_usecase(out->usecase)) {
10923 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10924 compress_pause(out->compr);
10925 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010926 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010927 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10928 out_set_voip_volume(&out->stream, (float)0, (float)0);
10929 else
10930 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10931
Zhou Song8edbbdb2021-01-14 16:48:03 +080010932 /* wait for stale pcm drained before switching to speaker */
10933 uint32_t latency =
10934 (out->config.period_count * out->config.period_size * 1000) /
10935 (out->config.rate);
10936 usleep(latency * 1000);
10937 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010938 }
10939 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010940 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10941 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010942 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010943 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10944 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010945 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010946 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010947 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010948 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010949 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010950 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010951 ALOGV("%s: exit", __func__);
10952 return 0;
10953}
10954
Haynes Mathew George01156f92018-04-13 15:29:54 -070010955void adev_on_battery_status_changed(bool charging)
10956{
10957 pthread_mutex_lock(&adev->lock);
10958 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10959 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010960 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010961 pthread_mutex_unlock(&adev->lock);
10962}
10963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010964static int adev_open(const hw_module_t *module, const char *name,
10965 hw_device_t **device)
10966{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010967 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010968 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010969 char mixer_ctl_name[128] = {0};
10970 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010971
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010972 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010973 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10974
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010975 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010976 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010977 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010978 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010979 ALOGD("%s: returning existing instance of adev", __func__);
10980 ALOGD("%s: exit", __func__);
10981 pthread_mutex_unlock(&adev_init_lock);
10982 return 0;
10983 }
10984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010985 adev = calloc(1, sizeof(struct audio_device));
10986
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010987 if (!adev) {
10988 pthread_mutex_unlock(&adev_init_lock);
10989 return -ENOMEM;
10990 }
10991
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010992 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10993
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010994 // register audio ext hidl at the earliest
10995 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010996#ifdef DYNAMIC_LOG_ENABLED
10997 register_for_dynamic_logging("hal");
10998#endif
10999
Derek Chenf939fb72018-11-13 13:34:41 -080011000 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011001 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011002 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11003 maj_version = atoi(value);
11004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011005 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011006 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011007 adev->device.common.module = (struct hw_module_t *)module;
11008 adev->device.common.close = adev_close;
11009
11010 adev->device.init_check = adev_init_check;
11011 adev->device.set_voice_volume = adev_set_voice_volume;
11012 adev->device.set_master_volume = adev_set_master_volume;
11013 adev->device.get_master_volume = adev_get_master_volume;
11014 adev->device.set_master_mute = adev_set_master_mute;
11015 adev->device.get_master_mute = adev_get_master_mute;
11016 adev->device.set_mode = adev_set_mode;
11017 adev->device.set_mic_mute = adev_set_mic_mute;
11018 adev->device.get_mic_mute = adev_get_mic_mute;
11019 adev->device.set_parameters = adev_set_parameters;
11020 adev->device.get_parameters = adev_get_parameters;
11021 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11022 adev->device.open_output_stream = adev_open_output_stream;
11023 adev->device.close_output_stream = adev_close_output_stream;
11024 adev->device.open_input_stream = adev_open_input_stream;
11025 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011026 adev->device.create_audio_patch = adev_create_audio_patch;
11027 adev->device.release_audio_patch = adev_release_audio_patch;
11028 adev->device.get_audio_port = adev_get_audio_port;
11029 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011030 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011031 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011032
11033 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011034 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011035 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011036 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011037 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011038 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011039 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011040 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011041 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011042 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011043 /* Init audio and voice feature */
11044 audio_extn_feature_init();
11045 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011046 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011047 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011048 list_init(&adev->active_inputs_list);
11049 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011050 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011051 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11052 audio_extn_utils_hash_eq);
11053 if (!adev->io_streams_map) {
11054 ALOGE("%s: Could not create io streams map", __func__);
11055 ret = -ENOMEM;
11056 goto adev_open_err;
11057 }
11058 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11059 audio_extn_utils_hash_eq);
11060 if (!adev->patch_map) {
11061 ALOGE("%s: Could not create audio patch map", __func__);
11062 ret = -ENOMEM;
11063 goto adev_open_err;
11064 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011065 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011066 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011067 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011068 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011069 adev->perf_lock_opts[0] = 0x101;
11070 adev->perf_lock_opts[1] = 0x20E;
11071 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011072 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011073 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011074 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011075 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011076 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011077 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011078
Zhou Song68ebc352019-12-05 17:11:15 +080011079 audio_extn_perf_lock_init();
11080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011081 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011082 adev->platform = platform_init(adev);
11083 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011084 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011085 ret = -EINVAL;
11086 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011087 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011088
Aalique Grahame22e49102018-12-18 14:23:57 -080011089 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011090 if (audio_extn_qap_is_enabled()) {
11091 ret = audio_extn_qap_init(adev);
11092 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011093 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011094 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011095 }
11096 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11097 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11098 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011099
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011100 if (audio_extn_qaf_is_enabled()) {
11101 ret = audio_extn_qaf_init(adev);
11102 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011103 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011104 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011105 }
11106
11107 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11108 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11109 }
11110
Derek Chenae7b0342019-02-08 15:17:04 -080011111 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011112 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11113
Eric Laurentc4aef752013-09-12 17:45:53 -070011114 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11115 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11116 if (adev->visualizer_lib == NULL) {
11117 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11118 } else {
11119 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11120 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011121 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011122 "visualizer_hal_start_output");
11123 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011124 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011125 "visualizer_hal_stop_output");
11126 }
11127 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011128 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011129 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011130 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011131 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011132 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011133 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011134
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011135 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11136 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11137 if (adev->offload_effects_lib == NULL) {
11138 ALOGE("%s: DLOPEN failed for %s", __func__,
11139 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11140 } else {
11141 ALOGV("%s: DLOPEN successful for %s", __func__,
11142 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11143 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011144 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011145 "offload_effects_bundle_hal_start_output");
11146 adev->offload_effects_stop_output =
11147 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11148 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011149 adev->offload_effects_set_hpx_state =
11150 (int (*)(bool))dlsym(adev->offload_effects_lib,
11151 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011152 adev->offload_effects_get_parameters =
11153 (void (*)(struct str_parms *, struct str_parms *))
11154 dlsym(adev->offload_effects_lib,
11155 "offload_effects_bundle_get_parameters");
11156 adev->offload_effects_set_parameters =
11157 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11158 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011159 }
11160 }
11161
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011162 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11163 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11164 if (adev->adm_lib == NULL) {
11165 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11166 } else {
11167 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11168 adev->adm_init = (adm_init_t)
11169 dlsym(adev->adm_lib, "adm_init");
11170 adev->adm_deinit = (adm_deinit_t)
11171 dlsym(adev->adm_lib, "adm_deinit");
11172 adev->adm_register_input_stream = (adm_register_input_stream_t)
11173 dlsym(adev->adm_lib, "adm_register_input_stream");
11174 adev->adm_register_output_stream = (adm_register_output_stream_t)
11175 dlsym(adev->adm_lib, "adm_register_output_stream");
11176 adev->adm_deregister_stream = (adm_deregister_stream_t)
11177 dlsym(adev->adm_lib, "adm_deregister_stream");
11178 adev->adm_request_focus = (adm_request_focus_t)
11179 dlsym(adev->adm_lib, "adm_request_focus");
11180 adev->adm_abandon_focus = (adm_abandon_focus_t)
11181 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011182 adev->adm_set_config = (adm_set_config_t)
11183 dlsym(adev->adm_lib, "adm_set_config");
11184 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11185 dlsym(adev->adm_lib, "adm_request_focus_v2");
11186 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11187 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11188 adev->adm_on_routing_change = (adm_on_routing_change_t)
11189 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011190 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11191 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011192 }
11193 }
11194
Aalique Grahame22e49102018-12-18 14:23:57 -080011195 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011196 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011197 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011198 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011199 //initialize this to false for now,
11200 //this will be set to true through set param
11201 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011202
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011203 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011204 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011205
11206 if (k_enable_extended_precision)
11207 adev_verify_devices(adev);
11208
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011209 adev->dsp_bit_width_enforce_mode =
11210 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011211
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011212 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11213 &adev->streams_output_cfg_list,
11214 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011215
Kiran Kandi910e1862013-10-29 13:29:42 -070011216 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011217
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011218 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011219 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011220 trial = atoi(value);
11221 if (period_size_is_plausible_for_low_latency(trial)) {
11222 pcm_config_low_latency.period_size = trial;
11223 pcm_config_low_latency.start_threshold = trial / 4;
11224 pcm_config_low_latency.avail_min = trial / 4;
11225 configured_low_latency_capture_period_size = trial;
11226 }
11227 }
ronghuiz93177262021-04-21 19:58:13 +080011228 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011229 trial = atoi(value);
11230 if (period_size_is_plausible_for_low_latency(trial)) {
11231 configured_low_latency_capture_period_size = trial;
11232 }
11233 }
11234
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011235 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11236
Eric Laurent4b084132018-10-19 17:33:43 -070011237 adev->camera_orientation = CAMERA_DEFAULT;
11238
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011239 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011240 af_period_multiplier = atoi(value);
11241 if (af_period_multiplier < 0)
11242 af_period_multiplier = 2;
11243 else if (af_period_multiplier > 4)
11244 af_period_multiplier = 4;
11245
11246 ALOGV("new period_multiplier = %d", af_period_multiplier);
11247 }
11248
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011249 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011250
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011251 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011252 pthread_mutex_unlock(&adev_init_lock);
11253
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011254 if (adev->adm_init)
11255 adev->adm_data = adev->adm_init();
11256
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011257 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011258 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011259
11260 audio_extn_snd_mon_init();
11261 pthread_mutex_lock(&adev->lock);
11262 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11263 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011264 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11265 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011266 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11267 /*
11268 * if the battery state callback happens before charging can be queried,
11269 * it will be guarded with the adev->lock held in the cb function and so
11270 * the callback value will reflect the latest state
11271 */
11272 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011273 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011274 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011275 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011276 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011277 /* Allocate memory for Device config params */
11278 adev->device_cfg_params = (struct audio_device_config_param*)
11279 calloc(platform_get_max_codec_backend(),
11280 sizeof(struct audio_device_config_param));
11281 if (adev->device_cfg_params == NULL)
11282 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011283
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011284 /*
11285 * Check if new PSPD matrix mixer control is supported. If not
11286 * supported, then set flag so that old mixer ctrl is sent while
11287 * sending pspd coefficients on older kernel version. Query mixer
11288 * control for default pcm id and channel value one.
11289 */
11290 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11291 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11292
11293 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11294 if (!ctl) {
11295 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11296 __func__, mixer_ctl_name);
11297 adev->use_old_pspd_mix_ctrl = true;
11298 }
11299
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011300 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011301 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011302
11303adev_open_err:
11304 free_map(adev->patch_map);
11305 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011306 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011307 pthread_mutex_destroy(&adev->lock);
11308 free(adev);
11309 adev = NULL;
11310 *device = NULL;
11311 pthread_mutex_unlock(&adev_init_lock);
11312 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011313}
11314
11315static struct hw_module_methods_t hal_module_methods = {
11316 .open = adev_open,
11317};
11318
11319struct audio_module HAL_MODULE_INFO_SYM = {
11320 .common = {
11321 .tag = HARDWARE_MODULE_TAG,
11322 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11323 .hal_api_version = HARDWARE_HAL_API_VERSION,
11324 .id = AUDIO_HARDWARE_MODULE_ID,
11325 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011326 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011327 .methods = &hal_module_methods,
11328 },
11329};