blob: d231a337335c42f4f5daccf500b5fabf41ba3cad [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",
Susan Wang117cf6f2022-04-06 20:11:46 -0400492 [USECASE_AUDIO_PLAYBACK_ALERTS] = "alerts-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800493 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700494 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530495 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500496 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400497
498 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
499 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
500 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800501 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500502 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700503};
504
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700505static const audio_usecase_t offload_usecases[] = {
506 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700507 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
508 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
509 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
510 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
511 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
512 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
513 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
514 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700515};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800516
Varun Balaraje49253e2017-07-06 19:48:56 +0530517static const audio_usecase_t interactive_usecases[] = {
518 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
519 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
520 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
521 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
522 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
523 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
524 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
525 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
526};
527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528#define STRING_TO_ENUM(string) { #string, string }
529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800530struct string_to_enum {
531 const char *name;
532 uint32_t value;
533};
534
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700535static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800536 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800537 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
538 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
539 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700540 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800541 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
542 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800543 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700544 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
545 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
546 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
547 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
548 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
549 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
550 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
551 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
552 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
553 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
554 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555};
556
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700557static const struct string_to_enum formats_name_to_enum_table[] = {
558 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
559 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
560 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700561 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
562 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
563 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700564 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800565 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
566 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700567 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800568};
569
570//list of all supported sample rates by HDMI specification.
571static const int out_hdmi_sample_rates[] = {
572 32000, 44100, 48000, 88200, 96000, 176400, 192000,
573};
574
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700575static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800576 STRING_TO_ENUM(32000),
577 STRING_TO_ENUM(44100),
578 STRING_TO_ENUM(48000),
579 STRING_TO_ENUM(88200),
580 STRING_TO_ENUM(96000),
581 STRING_TO_ENUM(176400),
582 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800583 STRING_TO_ENUM(352800),
584 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700585};
586
Carter Hsu2e429db2019-05-14 18:50:52 +0800587struct in_effect_list {
588 struct listnode list;
589 effect_handle_t handle;
590};
591
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530592static const audio_usecase_t record_usecases[] = {
593 USECASE_AUDIO_RECORD,
594 USECASE_AUDIO_RECORD2,
595 USECASE_AUDIO_RECORD3,
596};
597
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700598static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700599static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700600static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700601//cache last MBDRC cal step level
602static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700603
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530604static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700605static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800606static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530607static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530608#ifdef SOFT_VOLUME
609static int out_set_soft_volume_params(struct audio_stream_out *stream);
610#endif
Derek Chen6f293672019-04-01 01:40:24 -0700611static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
612static void in_snd_mon_cb(void * stream, struct str_parms * parms);
613static void out_snd_mon_cb(void * stream, struct str_parms * parms);
614
Zhou Song331c8e52019-08-26 14:16:12 +0800615static int configure_btsco_sample_rate(snd_device_t snd_device);
616
Vatsal Buchac09ae062018-11-14 13:25:08 +0530617#ifdef AUDIO_FEATURE_ENABLED_GCOV
618extern void __gcov_flush();
619static void enable_gcov()
620{
621 __gcov_flush();
622}
623#else
624static void enable_gcov()
625{
626}
627#endif
628
justinweng20fb6d82019-02-21 18:49:00 -0700629static int in_set_microphone_direction(const struct audio_stream_in *stream,
630 audio_microphone_direction_t dir);
631static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
632
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530633static bool is_pcm_record_usecase(audio_usecase_t uc_id)
634{
635 unsigned int record_uc_index;
636 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
637
638 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
639 if (uc_id == record_usecases[record_uc_index])
640 return true;
641 }
642 return false;
643}
644
645static audio_usecase_t get_record_usecase(struct audio_device *adev)
646{
647 audio_usecase_t ret_uc = USECASE_INVALID;
648 unsigned int record_uc_index;
649 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
650
651 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
652 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
653 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
654 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
655 ret_uc = record_usecases[record_uc_index];
656 break;
657 }
658 }
659
660 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
661 return ret_uc;
662}
663
664static void free_record_usecase(struct audio_device *adev,
665 audio_usecase_t uc_id)
666{
667 unsigned int record_uc_index;
668 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
669
670 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
671 if (record_usecases[record_uc_index] == uc_id) {
672 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
673 break;
674 }
675 }
676 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
677}
678
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700679static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
680 int flags __unused)
681{
682 int dir = 0;
683 switch (uc_id) {
684 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530685 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700686 dir = 1;
687 case USECASE_AUDIO_PLAYBACK_ULL:
688 break;
689 default:
690 return false;
691 }
692
693 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
694 PCM_PLAYBACK : PCM_CAPTURE);
695 if (adev->adm_is_noirq_avail)
696 return adev->adm_is_noirq_avail(adev->adm_data,
697 adev->snd_card, dev_id, dir);
698 return false;
699}
700
701static void register_out_stream(struct stream_out *out)
702{
703 struct audio_device *adev = out->dev;
704 if (is_offload_usecase(out->usecase) ||
705 !adev->adm_register_output_stream)
706 return;
707
708 // register stream first for backward compatibility
709 adev->adm_register_output_stream(adev->adm_data,
710 out->handle,
711 out->flags);
712
713 if (!adev->adm_set_config)
714 return;
715
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530716 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
717 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700718 out->handle,
719 out->pcm, &out->config);
720}
721
722static void register_in_stream(struct stream_in *in)
723{
724 struct audio_device *adev = in->dev;
725 if (!adev->adm_register_input_stream)
726 return;
727
728 adev->adm_register_input_stream(adev->adm_data,
729 in->capture_handle,
730 in->flags);
731
732 if (!adev->adm_set_config)
733 return;
734
735 if (in->realtime)
736 adev->adm_set_config(adev->adm_data,
737 in->capture_handle,
738 in->pcm,
739 &in->config);
740}
741
742static void request_out_focus(struct stream_out *out, long ns)
743{
744 struct audio_device *adev = out->dev;
745
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700746 if (adev->adm_request_focus_v2)
747 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
748 else if (adev->adm_request_focus)
749 adev->adm_request_focus(adev->adm_data, out->handle);
750}
751
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700752static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700753{
754 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700755 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700756
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700757 if (adev->adm_request_focus_v2_1)
758 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
759 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700760 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
761 else if (adev->adm_request_focus)
762 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700763
764 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700765}
766
767static void release_out_focus(struct stream_out *out)
768{
769 struct audio_device *adev = out->dev;
770
771 if (adev->adm_abandon_focus)
772 adev->adm_abandon_focus(adev->adm_data, out->handle);
773}
774
775static void release_in_focus(struct stream_in *in)
776{
777 struct audio_device *adev = in->dev;
778 if (adev->adm_abandon_focus)
779 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
780}
781
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530782static int parse_snd_card_status(struct str_parms *parms, int *card,
783 card_status_t *status)
784{
785 char value[32]={0};
786 char state[32]={0};
787
788 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
789 if (ret < 0)
790 return -1;
791
792 // sscanf should be okay as value is of max length 32.
793 // same as sizeof state.
794 if (sscanf(value, "%d,%s", card, state) < 2)
795 return -1;
796
797 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
798 CARD_STATUS_OFFLINE;
799 return 0;
800}
801
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700802static inline void adjust_frames_for_device_delay(struct stream_out *out,
803 uint32_t *dsp_frames) {
804 // Adjustment accounts for A2dp encoder latency with offload usecases
805 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800806 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700807 unsigned long offset =
808 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
809 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
810 }
811}
812
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700813static inline bool free_entry(void *key __unused,
814 void *value, void *context __unused)
815{
816 free(value);
817 return true;
818}
819
820static inline void free_map(Hashmap *map)
821{
822 if (map) {
823 hashmapForEach(map, free_entry, (void *) NULL);
824 hashmapFree(map);
825 }
826}
827
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800828static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700829 audio_patch_handle_t patch_handle)
830{
831 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
832 return;
833
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700834 struct audio_patch_info *p_info =
835 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
836 if (p_info) {
837 ALOGV("%s: Remove patch %d", __func__, patch_handle);
838 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
839 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700840 free(p_info);
841 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700842}
843
844static inline int io_streams_map_insert(struct audio_device *adev,
845 struct audio_stream *stream,
846 audio_io_handle_t handle,
847 audio_patch_handle_t patch_handle)
848{
849 struct audio_stream_info *s_info =
850 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
851
852 if (s_info == NULL) {
853 ALOGE("%s: Could not allocate stream info", __func__);
854 return -ENOMEM;
855 }
856 s_info->stream = stream;
857 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700858
859 pthread_mutex_lock(&adev->lock);
860 struct audio_stream_info *stream_info =
861 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700862 if (stream_info != NULL)
863 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800864 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700865 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700866 return 0;
867}
868
869static inline void io_streams_map_remove(struct audio_device *adev,
870 audio_io_handle_t handle)
871{
872 pthread_mutex_lock(&adev->lock);
873 struct audio_stream_info *s_info =
874 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700875 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800876 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700877 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800878 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700879 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800880done:
881 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700882 return;
883}
884
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800885static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700886 audio_patch_handle_t handle)
887{
888 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700889 p_info = (struct audio_patch_info *)
890 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700891 return p_info;
892}
893
vivek mehtaa76401a2015-04-24 14:12:15 -0700894__attribute__ ((visibility ("default")))
895bool audio_hw_send_gain_dep_calibration(int level) {
896 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700897 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700898
899 pthread_mutex_lock(&adev_init_lock);
900
901 if (adev != NULL && adev->platform != NULL) {
902 pthread_mutex_lock(&adev->lock);
903 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700904
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530905 // cache level info for any of the use case which
906 // was not started.
907 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700908
vivek mehtaa76401a2015-04-24 14:12:15 -0700909 pthread_mutex_unlock(&adev->lock);
910 } else {
911 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
912 }
913
914 pthread_mutex_unlock(&adev_init_lock);
915
916 return ret_val;
917}
918
Ashish Jain5106d362016-05-11 19:23:33 +0530919static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
920{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800921 bool gapless_enabled = false;
922 const char *mixer_ctl_name = "Compress Gapless Playback";
923 struct mixer_ctl *ctl;
924
925 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700926 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530927
928 /*Disable gapless if its AV playback*/
929 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800930
931 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
932 if (!ctl) {
933 ALOGE("%s: Could not get ctl for mixer cmd - %s",
934 __func__, mixer_ctl_name);
935 return -EINVAL;
936 }
937
938 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
939 ALOGE("%s: Could not set gapless mode %d",
940 __func__, gapless_enabled);
941 return -EINVAL;
942 }
943 return 0;
944}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700945
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700946__attribute__ ((visibility ("default")))
947int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
948 int table_size) {
949 int ret_val = 0;
950 ALOGV("%s: enter ... ", __func__);
951
952 pthread_mutex_lock(&adev_init_lock);
953 if (adev == NULL) {
954 ALOGW("%s: adev is NULL .... ", __func__);
955 goto done;
956 }
957
958 pthread_mutex_lock(&adev->lock);
959 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
960 pthread_mutex_unlock(&adev->lock);
961done:
962 pthread_mutex_unlock(&adev_init_lock);
963 ALOGV("%s: exit ... ", __func__);
964 return ret_val;
965}
966
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800967bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800968{
969 bool ret = false;
970 ALOGV("%s: enter ...", __func__);
971
972 pthread_mutex_lock(&adev_init_lock);
973
974 if (adev != NULL && adev->platform != NULL) {
975 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800976 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800977 pthread_mutex_unlock(&adev->lock);
978 }
979
980 pthread_mutex_unlock(&adev_init_lock);
981
982 ALOGV("%s: exit with ret %d", __func__, ret);
983 return ret;
984}
Aalique Grahame22e49102018-12-18 14:23:57 -0800985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700986static bool is_supported_format(audio_format_t format)
987{
Eric Laurent86e17132013-09-12 17:49:30 -0700988 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530989 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530990 format == AUDIO_FORMAT_AAC_LC ||
991 format == AUDIO_FORMAT_AAC_HE_V1 ||
992 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530993 format == AUDIO_FORMAT_AAC_ADTS_LC ||
994 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
995 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530996 format == AUDIO_FORMAT_AAC_LATM_LC ||
997 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
998 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530999 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
1000 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301001 format == AUDIO_FORMAT_PCM_FLOAT ||
1002 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001003 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301004 format == AUDIO_FORMAT_AC3 ||
1005 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001006 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301007 format == AUDIO_FORMAT_DTS ||
1008 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001009 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301010 format == AUDIO_FORMAT_ALAC ||
1011 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301012 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301013 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001014 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301015 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001016 format == AUDIO_FORMAT_APTX ||
1017 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001018 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001019
1020 return false;
1021}
1022
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001023static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1024{
1025 struct listnode *node;
1026 struct audio_usecase *usecase;
1027
1028 list_for_each(node, &adev->usecase_list) {
1029 usecase = node_to_item(node, struct audio_usecase, list);
1030 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1031 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1032 return false;
1033 }
1034 }
1035
1036 return true;
1037}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001038static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1039{
1040 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001041 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001042 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1043}
1044
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001045static inline bool is_valid_volume(float left, float right)
1046{
1047 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1048}
1049
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301050static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301051{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301052 ALOGV("%s", __func__);
1053 audio_route_apply_and_update_path(adev->audio_route,
1054 "asrc-mode");
1055 adev->asrc_mode_enabled = true;
1056}
1057
1058static void disable_asrc_mode(struct audio_device *adev)
1059{
1060 ALOGV("%s", __func__);
1061 audio_route_reset_and_update_path(adev->audio_route,
1062 "asrc-mode");
1063 adev->asrc_mode_enabled = false;
1064}
1065
Saurav Kumarc1411662020-10-14 10:50:45 +05301066static void check_and_configure_headphone(struct audio_device *adev,
1067 struct audio_usecase *uc_info,
1068 snd_device_t snd_device)
1069{
1070 struct listnode *node;
1071 struct audio_usecase *usecase;
1072 int new_backend_idx, usecase_backend_idx;
1073 bool spkr_hph_single_be_native_concurrency;
1074
1075 new_backend_idx = platform_get_backend_index(snd_device);
1076 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001077 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1078 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301079 list_for_each(node, &adev->usecase_list) {
1080 usecase = node_to_item(node, struct audio_usecase, list);
1081 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1082 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1083 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1084 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1085 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1086 disable_audio_route(adev, usecase);
1087 disable_snd_device(adev, usecase->out_snd_device);
1088 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301089 platform_check_and_set_codec_backend_cfg(adev, usecase,
1090 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301091 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001092 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301093 }
1094 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001095 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1096 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1097 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1098 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1099 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1100 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1101 platform_check_and_set_codec_backend_cfg(adev, usecase,
1102 usecase->out_snd_device);
1103 }
1104 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301105 }
1106 }
1107}
1108
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301109/*
1110 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1111 * 44.1 or Native DSD backends are enabled for any of current use case.
1112 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1113 * - Disable current mix path use case(Headphone backend) and re-enable it with
1114 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1115 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1116 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301117static void check_and_set_asrc_mode(struct audio_device *adev,
1118 struct audio_usecase *uc_info,
1119 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301120{
1121 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301122 int i, num_new_devices = 0;
1123 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1124 /*
1125 *Split snd device for new combo use case
1126 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1127 */
1128 if (platform_split_snd_device(adev->platform,
1129 snd_device,
1130 &num_new_devices,
1131 split_new_snd_devices) == 0) {
1132 for (i = 0; i < num_new_devices; i++)
1133 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1134 } else {
1135 int new_backend_idx = platform_get_backend_index(snd_device);
1136 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1137 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1138 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1139 !adev->asrc_mode_enabled) {
1140 struct listnode *node = NULL;
1141 struct audio_usecase *uc = NULL;
1142 struct stream_out *curr_out = NULL;
1143 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1144 int i, num_devices, ret = 0;
1145 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301146
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301147 list_for_each(node, &adev->usecase_list) {
1148 uc = node_to_item(node, struct audio_usecase, list);
1149 curr_out = (struct stream_out*) uc->stream.out;
1150 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1151 /*
1152 *Split snd device for existing combo use case
1153 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1154 */
1155 ret = platform_split_snd_device(adev->platform,
1156 uc->out_snd_device,
1157 &num_devices,
1158 split_snd_devices);
1159 if (ret < 0 || num_devices == 0) {
1160 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1161 split_snd_devices[0] = uc->out_snd_device;
1162 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001163 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301164 for (i = 0; i < num_devices; i++) {
1165 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1166 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1167 if((new_backend_idx == HEADPHONE_BACKEND) &&
1168 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1169 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001170 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301171 __func__);
1172 enable_asrc_mode(adev);
1173 break;
1174 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1175 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1176 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001177 ALOGV("%s: 48K stream detected, disabling and enabling it \
1178 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301179 disable_audio_route(adev, uc);
1180 disable_snd_device(adev, uc->out_snd_device);
1181 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1182 if (new_backend_idx == DSD_NATIVE_BACKEND)
1183 audio_route_apply_and_update_path(adev->audio_route,
1184 "hph-true-highquality-mode");
1185 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1186 (curr_out->bit_width >= 24))
1187 audio_route_apply_and_update_path(adev->audio_route,
1188 "hph-highquality-mode");
1189 enable_asrc_mode(adev);
1190 enable_snd_device(adev, uc->out_snd_device);
1191 enable_audio_route(adev, uc);
1192 break;
1193 }
1194 }
1195 // reset split devices count
1196 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001197 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301198 if (adev->asrc_mode_enabled)
1199 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301200 }
1201 }
1202 }
1203}
1204
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001205static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1206 struct audio_effect_config effect_config,
1207 unsigned int param_value)
1208{
1209 char mixer_ctl_name[] = "Audio Effect";
1210 struct mixer_ctl *ctl;
1211 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001212 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001213
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001214 if (in == NULL) {
1215 ALOGE("%s: active input stream is NULL", __func__);
1216 return -EINVAL;
1217 }
1218
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001219 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1220 if (!ctl) {
1221 ALOGE("%s: Could not get mixer ctl - %s",
1222 __func__, mixer_ctl_name);
1223 return -EINVAL;
1224 }
1225
1226 set_values[0] = 1; //0:Rx 1:Tx
1227 set_values[1] = in->app_type_cfg.app_type;
1228 set_values[2] = (long)effect_config.module_id;
1229 set_values[3] = (long)effect_config.instance_id;
1230 set_values[4] = (long)effect_config.param_id;
1231 set_values[5] = param_value;
1232
1233 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1234
1235 return 0;
1236
1237}
1238
1239static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1240 int effect_type, unsigned int *param_value)
1241{
1242 int ret = 0;
1243 struct audio_effect_config other_effect_config;
1244 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001245 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001246
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001247 if (in == NULL) {
1248 ALOGE("%s: active input stream is NULL", __func__);
1249 return -EINVAL;
1250 }
1251
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001252 usecase = get_usecase_from_list(adev, in->usecase);
1253 if (!usecase)
1254 return -EINVAL;
1255
1256 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1257 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1258 if (ret < 0) {
1259 ALOGE("%s Failed to get effect params %d", __func__, ret);
1260 return ret;
1261 }
1262
1263 if (module_id == other_effect_config.module_id) {
1264 //Same module id for AEC/NS. Values need to be combined
1265 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1266 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1267 *param_value |= other_effect_config.param_value;
1268 }
1269 }
1270
1271 return ret;
1272}
1273
1274static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301275{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001276 struct audio_effect_config effect_config;
1277 struct audio_usecase *usecase = NULL;
1278 int ret = 0;
1279 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001280 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001281
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001282 if(!voice_extn_is_dynamic_ecns_enabled())
1283 return ENOSYS;
1284
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001285 if (!in) {
1286 ALOGE("%s: Invalid input stream", __func__);
1287 return -EINVAL;
1288 }
1289
1290 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1291
1292 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001293 if (usecase == NULL) {
1294 ALOGE("%s: Could not find the usecase (%d) in the list",
1295 __func__, in->usecase);
1296 return -EINVAL;
1297 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001298
1299 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1300 if (ret < 0) {
1301 ALOGE("%s Failed to get module id %d", __func__, ret);
1302 return ret;
1303 }
1304 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1305 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1306
1307 if(enable)
1308 param_value = effect_config.param_value;
1309
1310 /*Special handling for AEC & NS effects Param values need to be
1311 updated if module ids are same*/
1312
1313 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1314 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1315 if (ret < 0)
1316 return ret;
1317 }
1318
1319 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1320
1321 return ret;
1322}
1323
1324static void check_and_enable_effect(struct audio_device *adev)
1325{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001326 if(!voice_extn_is_dynamic_ecns_enabled())
1327 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001328
Eric Laurent637e2d42018-11-15 12:24:31 -08001329 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001330
Eric Laurent637e2d42018-11-15 12:24:31 -08001331 if (in != NULL && !in->standby) {
1332 if (in->enable_aec)
1333 enable_disable_effect(adev, EFFECT_AEC, true);
1334
1335 if (in->enable_ns &&
1336 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1337 enable_disable_effect(adev, EFFECT_NS, true);
1338 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001339 }
1340}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001341
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001342int pcm_ioctl(struct pcm *pcm, int request, ...)
1343{
1344 va_list ap;
1345 void * arg;
1346 int pcm_fd = *(int*)pcm;
1347
1348 va_start(ap, request);
1349 arg = va_arg(ap, void *);
1350 va_end(ap);
1351
1352 return ioctl(pcm_fd, request, arg);
1353}
1354
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001355int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001356 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001359 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301360 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301361 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001362 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301363 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001364
1365 if (usecase == NULL)
1366 return -EINVAL;
1367
1368 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1369
Carter Hsu2e429db2019-05-14 18:50:52 +08001370 if (usecase->type == PCM_CAPTURE) {
1371 struct stream_in *in = usecase->stream.in;
1372 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001374
1375 if (in) {
1376 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001377 list_init(&out_devices);
1378 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001379 struct listnode *node;
1380 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1381 USECASE_AUDIO_PLAYBACK_VOIP);
1382 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001383 assign_devices(&out_devices,
1384 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001385 } else if (adev->primary_output &&
1386 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001387 assign_devices(&out_devices,
1388 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001389 } else {
1390 list_for_each(node, &adev->usecase_list) {
1391 uinfo = node_to_item(node, struct audio_usecase, list);
1392 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001393 assign_devices(&out_devices,
1394 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001395 break;
1396 }
1397 }
1398 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001399
1400 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001401 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301402 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001403 }
1404 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001405 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1406 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1407 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001408 snd_device = usecase->in_snd_device;
1409 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001411 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001412
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001413 if (usecase->type == PCM_CAPTURE) {
1414 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1415 platform_set_fluence_nn_state(adev->platform, true);
1416 ALOGD("%s: set fluence nn capture state", __func__);
1417 }
1418 }
1419
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001420#ifdef DS1_DOLBY_DAP_ENABLED
1421 audio_extn_dolby_set_dmid(adev);
1422 audio_extn_dolby_set_endpoint(adev);
1423#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001424 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001425 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301426 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001427 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001428 if (audio_extn_is_maxx_audio_enabled())
1429 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301430 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001431 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1432 out = usecase->stream.out;
1433 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301434 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1435 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301436
1437 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001438 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1439 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1440 adev->fluence_nn_usecase_id = usecase->id;
1441 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1442 }
1443 }
1444
1445 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301446 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001447 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301448 ALOGD("%s: set custom mtmx params v1", __func__);
1449 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1450 }
1451 } else {
1452 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1453 }
Manish Dewangan58229382017-02-02 15:48:41 +05301454
Andy Hung756ecc12018-10-19 17:47:12 -07001455 // we shouldn't truncate mixer_path
1456 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1457 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1458 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001459 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001460 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301461 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1462 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1463 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1464 if (parms) {
1465 audio_extn_fm_set_parameters(adev, parms);
1466 str_parms_destroy(parms);
1467 }
1468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 ALOGV("%s: exit", __func__);
1470 return 0;
1471}
1472
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001473int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001474 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001477 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301478 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001479
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301480 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001481 return -EINVAL;
1482
1483 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301484 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 snd_device = usecase->in_snd_device;
1486 else
1487 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001488
1489 /* disable island and power mode on supported device for voice call */
1490 if (usecase->type == VOICE_CALL) {
1491 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1492 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1493 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1494 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1495 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1496 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001497 if (voice_is_lte_call_active(adev))
1498 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001499 ALOGD("%s: disable island cfg and power mode in voice tx path",
1500 __func__);
1501 }
1502 }
1503 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1504 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1505 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1506 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1507 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1508 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1509 ALOGD("%s: disable island cfg and power mode in voice rx path",
1510 __func__);
1511 }
1512 }
1513 }
1514
Andy Hung756ecc12018-10-19 17:47:12 -07001515 // we shouldn't truncate mixer_path
1516 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1517 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1518 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001519 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001520 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001521 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001522 if (usecase->type == PCM_CAPTURE) {
1523 struct stream_in *in = usecase->stream.in;
1524 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001525 struct listnode out_devices;
1526 list_init(&out_devices);
1527 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001528 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301529 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001530 }
1531 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001532 if (usecase->id == adev->fluence_nn_usecase_id) {
1533 platform_set_fluence_nn_state(adev->platform, false);
1534 adev->fluence_nn_usecase_id = USECASE_INVALID;
1535 ALOGD("%s: reset fluence nn capture state", __func__);
1536 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001537 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301538 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301539
1540 if (usecase->type == PCM_CAPTURE) {
1541 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001542 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301543 ALOGD("%s: reset custom mtmx params v1", __func__);
1544 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1545 }
1546 } else {
1547 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1548 }
1549
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001550 if ((usecase->type == PCM_PLAYBACK) &&
1551 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301552 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 ALOGV("%s: exit", __func__);
1555 return 0;
1556}
1557
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001558int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001559 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301561 int i, num_devices = 0;
1562 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001563 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1564
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001565 if (snd_device < SND_DEVICE_MIN ||
1566 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001567 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001568 return -EINVAL;
1569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001571 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001572 ALOGE("%s: Invalid sound device returned", __func__);
1573 return -EINVAL;
1574 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001575
1576 adev->snd_dev_ref_cnt[snd_device]++;
1577
1578 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1579 (platform_split_snd_device(adev->platform,
1580 snd_device,
1581 &num_devices,
1582 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001583 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001584 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001585 /* Set backend config for A2DP to ensure slimbus configuration
1586 is correct if A2DP is already active and backend is closed
1587 and re-opened */
1588 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1589 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 return 0;
1591 }
1592
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001593 if (audio_extn_spkr_prot_is_enabled())
1594 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001595
Aalique Grahame22e49102018-12-18 14:23:57 -08001596 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1597
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001598 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1599 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001600 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1601 goto err;
1602 }
1603 audio_extn_dev_arbi_acquire(snd_device);
1604 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001605 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001606 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001607 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001608 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001609 } else if (platform_split_snd_device(adev->platform,
1610 snd_device,
1611 &num_devices,
1612 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301613 for (i = 0; i < num_devices; i++) {
1614 enable_snd_device(adev, new_snd_devices[i]);
1615 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001616 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001617 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001618 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301619
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001620 /* enable island and power mode on supported device */
1621 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1622 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1623 platform_set_island_cfg_on_device(adev, snd_device, true);
1624 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001625 if (voice_is_lte_call_active(adev) &&
1626 (snd_device >= SND_DEVICE_IN_BEGIN &&
1627 snd_device < SND_DEVICE_IN_END))
1628 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001629 ALOGD("%s: enable island cfg and power mode on: %s",
1630 __func__, device_name);
1631 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301632
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301633 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301634
1635 struct audio_usecase *usecase;
1636 struct listnode *node;
1637 /* Disable SCO Devices and enable handset mic for active input stream */
1638 list_for_each(node, &adev->usecase_list) {
1639 usecase = node_to_item(node, struct audio_usecase, list);
1640 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1641 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1642 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1643 reassign_device_list(&usecase->stream.in->device_list,
1644 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1645 select_devices(adev, usecase->id);
1646 }
1647 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301648 if (audio_extn_a2dp_start_playback() < 0) {
1649 ALOGE(" fail to configure A2dp Source control path ");
1650 goto err;
1651 } else {
1652 adev->a2dp_started = true;
1653 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001654 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001655
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001656 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1657 (audio_extn_a2dp_start_capture() < 0)) {
1658 ALOGE(" fail to configure A2dp Sink control path ");
1659 goto err;
1660 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301661
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001662 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1663 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1664 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1665 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1666 ALOGE(" fail to configure sco control path ");
1667 goto err;
1668 }
Zhou Song12c29502019-03-16 10:37:18 +08001669 }
1670
Zhou Song331c8e52019-08-26 14:16:12 +08001671 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001672 /* due to the possibility of calibration overwrite between listen
1673 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001674 audio_extn_sound_trigger_update_device_status(snd_device,
1675 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301676 audio_extn_listen_update_device_status(snd_device,
1677 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001678 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001679 audio_extn_sound_trigger_update_device_status(snd_device,
1680 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301681 audio_extn_listen_update_device_status(snd_device,
1682 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001683 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001684 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001685 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001686 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301687
1688 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1689 !adev->native_playback_enabled &&
1690 audio_is_true_native_stream_active(adev)) {
1691 ALOGD("%s: %d: napb: enabling native mode in hardware",
1692 __func__, __LINE__);
1693 audio_route_apply_and_update_path(adev->audio_route,
1694 "true-native-mode");
1695 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301696 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301697 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1698 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001699 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001700 ALOGD("%s: init ec ref loopback", __func__);
1701 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001705err:
1706 adev->snd_dev_ref_cnt[snd_device]--;
1707 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708}
1709
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001710int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001711 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301713 int i, num_devices = 0;
1714 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001715 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1716
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001717 if (snd_device < SND_DEVICE_MIN ||
1718 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001719 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001720 return -EINVAL;
1721 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001722
1723 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1724 ALOGE("%s: Invalid sound device returned", __func__);
1725 return -EINVAL;
1726 }
1727
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1729 ALOGE("%s: device ref cnt is already 0", __func__);
1730 return -EINVAL;
1731 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001732
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001733 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001734
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001735
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001736 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001737 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301738
Aalique Grahame22e49102018-12-18 14:23:57 -08001739 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1740
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001741 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1742 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001743 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001744
1745 // when speaker device is disabled, reset swap.
1746 // will be renabled on usecase start
1747 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001748 } else if (platform_split_snd_device(adev->platform,
1749 snd_device,
1750 &num_devices,
1751 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301752 for (i = 0; i < num_devices; i++) {
1753 disable_snd_device(adev, new_snd_devices[i]);
1754 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001755 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001756 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001757 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001758 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001759
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301760 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301761 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301762 adev->a2dp_started = false;
1763 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001764 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001765 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001766 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301767 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001768 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301769 adev->native_playback_enabled) {
1770 ALOGD("%s: %d: napb: disabling native mode in hardware",
1771 __func__, __LINE__);
1772 audio_route_reset_and_update_path(adev->audio_route,
1773 "true-native-mode");
1774 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001775 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301776 adev->asrc_mode_enabled) {
1777 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301778 disable_asrc_mode(adev);
1779 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001780 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301781 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001782 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001783 ALOGD("%s: deinit ec ref loopback", __func__);
1784 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1785 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001786
1787 audio_extn_utils_release_snd_device(snd_device);
1788 } else {
1789 if (platform_split_snd_device(adev->platform,
1790 snd_device,
1791 &num_devices,
1792 new_snd_devices) == 0) {
1793 for (i = 0; i < num_devices; i++) {
1794 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1795 }
1796 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 return 0;
1800}
1801
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001802/*
1803 legend:
1804 uc - existing usecase
1805 new_uc - new usecase
1806 d1, d11, d2 - SND_DEVICE enums
1807 a1, a2 - corresponding ANDROID device enums
1808 B1, B2 - backend strings
1809
1810case 1
1811 uc->dev d1 (a1) B1
1812 new_uc->dev d1 (a1), d2 (a2) B1, B2
1813
1814 resolution: disable and enable uc->dev on d1
1815
1816case 2
1817 uc->dev d1 (a1) B1
1818 new_uc->dev d11 (a1) B1
1819
1820 resolution: need to switch uc since d1 and d11 are related
1821 (e.g. speaker and voice-speaker)
1822 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1823
1824case 3
1825 uc->dev d1 (a1) B1
1826 new_uc->dev d2 (a2) B2
1827
1828 resolution: no need to switch uc
1829
1830case 4
1831 uc->dev d1 (a1) B1
1832 new_uc->dev d2 (a2) B1
1833
1834 resolution: disable enable uc-dev on d2 since backends match
1835 we cannot enable two streams on two different devices if they
1836 share the same backend. e.g. if offload is on speaker device using
1837 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1838 using the same backend, offload must also be switched to voice-handset.
1839
1840case 5
1841 uc->dev d1 (a1) B1
1842 new_uc->dev d1 (a1), d2 (a2) B1
1843
1844 resolution: disable enable uc-dev on d2 since backends match
1845 we cannot enable two streams on two different devices if they
1846 share the same backend.
1847
1848case 6
1849 uc->dev d1 (a1) B1
1850 new_uc->dev d2 (a1) B2
1851
1852 resolution: no need to switch
1853
1854case 7
1855 uc->dev d1 (a1), d2 (a2) B1, B2
1856 new_uc->dev d1 (a1) B1
1857
1858 resolution: no need to switch
1859
Zhou Song4ba65882018-07-09 14:48:07 +08001860case 8
1861 uc->dev d1 (a1) B1
1862 new_uc->dev d11 (a1), d2 (a2) B1, B2
1863 resolution: compared to case 1, for this case, d1 and d11 are related
1864 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301865
1866case 9
1867 uc->dev d1 (a1), d2(a2) B1 B2
1868 new_uc->dev d1 (a1), d22 (a2) B1, B2
1869 resolution: disable enable uc-dev on d2 since backends match
1870 we cannot enable two streams on two different devices if they
1871 share the same backend. This is special case for combo use case
1872 with a2dp and sco devices which uses same backend.
1873 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001874*/
1875static snd_device_t derive_playback_snd_device(void * platform,
1876 struct audio_usecase *uc,
1877 struct audio_usecase *new_uc,
1878 snd_device_t new_snd_device)
1879{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001880 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001881
1882 snd_device_t d1 = uc->out_snd_device;
1883 snd_device_t d2 = new_snd_device;
1884
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001885 list_init(&a1);
1886 list_init(&a2);
1887
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301888 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301889 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001890 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1891 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301892 break;
1893 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001894 assign_devices(&a1, &uc->stream.out->device_list);
1895 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301896 break;
1897 }
1898
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001899 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001900 if (!compare_devices(&a1, &a2) &&
1901 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001902 snd_device_t d3[2];
1903 int num_devices = 0;
1904 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001905 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001906 &num_devices,
1907 d3);
1908 if (ret < 0) {
1909 if (ret != -ENOSYS) {
1910 ALOGW("%s failed to split snd_device %d",
1911 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001912 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001913 }
1914 goto end;
1915 }
1916
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001917 if (platform_check_backends_match(d3[0], d3[1])) {
1918 return d2; // case 5
1919 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301920 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1921 platform_check_backends_match(d1, d2))
1922 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001923 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301924 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001925 // check if d1 is related to any of d3's
1926 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001927 return d1; // case 1
1928 else
1929 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001930 }
1931 } else {
1932 if (platform_check_backends_match(d1, d2)) {
1933 return d2; // case 2, 4
1934 } else {
1935 return d1; // case 6, 3
1936 }
1937 }
1938
Zhenlin Lian4f947842022-05-14 15:50:52 +05301939 clear_devices(&a1);
1940 clear_devices(&a2);
1941
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001942end:
1943 return d2; // return whatever was calculated before.
1944}
1945
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001946static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301947 struct audio_usecase *uc_info,
1948 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949{
1950 struct listnode *node;
1951 struct audio_usecase *usecase;
1952 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301953 snd_device_t uc_derive_snd_device;
1954 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001955 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1956 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001957 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301958 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001959 /*
1960 * This function is to make sure that all the usecases that are active on
1961 * the hardware codec backend are always routed to any one device that is
1962 * handled by the hardware codec.
1963 * For example, if low-latency and deep-buffer usecases are currently active
1964 * on speaker and out_set_parameters(headset) is received on low-latency
1965 * output, then we have to make sure deep-buffer is also switched to headset,
1966 * because of the limitation that both the devices cannot be enabled
1967 * at the same time as they share the same backend.
1968 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001969 /*
1970 * This call is to check if we need to force routing for a particular stream
1971 * If there is a backend configuration change for the device when a
1972 * new stream starts, then ADM needs to be closed and re-opened with the new
1973 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001974 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001975 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001976 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1977 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301978 /* For a2dp device reconfigure all active sessions
1979 * with new AFE encoder format based on a2dp state
1980 */
1981 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301982 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1983 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301984 audio_extn_a2dp_is_force_device_switch()) {
1985 force_routing = true;
1986 force_restart_session = true;
1987 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001988
1989 /*
1990 * Island cfg and power mode config needs to set before AFE port start.
1991 * Set force routing in case of voice device was enable before.
1992 */
1993 if (uc_info->type == VOICE_CALL &&
1994 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001995 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001996 platform_check_and_update_island_power_status(adev->platform,
1997 uc_info,
1998 snd_device)) {
1999 force_routing = true;
2000 ALOGD("%s:becf: force routing %d for power mode supported device",
2001 __func__, force_routing);
2002 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302003 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2004
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002005 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002006 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002007 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002008 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2009 switch_device[i] = false;
2010
2011 list_for_each(node, &adev->usecase_list) {
2012 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002013
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302014 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2015 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302016 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302017 platform_get_snd_device_name(usecase->out_snd_device),
2018 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302019 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2020 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302021 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2022 usecase, uc_info, snd_device);
2023 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002024 (is_codec_backend_out_device_type(&usecase->device_list) ||
2025 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2026 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2027 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2028 is_a2dp_out_device_type(&usecase->device_list) ||
2029 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302030 ((force_restart_session) ||
2031 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302032 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2033 __func__, use_case_table[usecase->id],
2034 platform_get_snd_device_name(usecase->out_snd_device));
2035 disable_audio_route(adev, usecase);
2036 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302037 /* Enable existing usecase on derived playback device */
2038 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302039 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302040 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002041 }
2042 }
2043
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302044 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2045 num_uc_to_switch);
2046
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002047 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002048 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302050 /* Make sure the previous devices to be disabled first and then enable the
2051 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052 list_for_each(node, &adev->usecase_list) {
2053 usecase = node_to_item(node, struct audio_usecase, list);
2054 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002055 /* Check if output sound device to be switched can be split and if any
2056 of the split devices match with derived sound device */
2057 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2058 &num_devices, split_snd_devices) == 0) {
2059 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2060 for (i = 0; i < num_devices; i++) {
2061 /* Disable devices that do not match with derived sound device */
2062 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2063 disable_snd_device(adev, split_snd_devices[i]);
2064 }
2065 } else {
2066 disable_snd_device(adev, usecase->out_snd_device);
2067 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 }
2069 }
2070
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002071 list_for_each(node, &adev->usecase_list) {
2072 usecase = node_to_item(node, struct audio_usecase, list);
2073 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002074 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2075 &num_devices, split_snd_devices) == 0) {
2076 /* Enable derived sound device only if it does not match with
2077 one of the split sound devices. This is because the matching
2078 sound device was not disabled */
2079 bool should_enable = true;
2080 for (i = 0; i < num_devices; i++) {
2081 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2082 should_enable = false;
2083 break;
2084 }
2085 }
2086 if (should_enable)
2087 enable_snd_device(adev, derive_snd_device[usecase->id]);
2088 } else {
2089 enable_snd_device(adev, derive_snd_device[usecase->id]);
2090 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002091 }
2092 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002093
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094 /* Re-route all the usecases on the shared backend other than the
2095 specified usecase to new snd devices */
2096 list_for_each(node, &adev->usecase_list) {
2097 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302098 /* Update the out_snd_device only before enabling the audio route */
2099 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302100 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302101 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2102 use_case_table[usecase->id],
2103 platform_get_snd_device_name(usecase->out_snd_device));
2104 /* Update voc calibration before enabling Voice/VoIP route */
2105 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2106 status = platform_switch_voice_call_device_post(adev->platform,
2107 usecase->out_snd_device,
2108 platform_get_input_snd_device(
2109 adev->platform, NULL,
2110 &uc_info->device_list,
2111 usecase->type));
2112 enable_audio_route(adev, usecase);
2113 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2114 out_set_voip_volume(&usecase->stream.out->stream,
2115 usecase->stream.out->volume_l,
2116 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302117 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002118 }
2119 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002120 }
2121}
2122
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302123static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002124 struct audio_usecase *uc_info,
2125 snd_device_t snd_device)
2126{
2127 struct listnode *node;
2128 struct audio_usecase *usecase;
2129 bool switch_device[AUDIO_USECASE_MAX];
2130 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002131 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002132 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002133
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302134 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2135 snd_device);
2136 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302137
2138 /*
2139 * Make sure out devices is checked against out codec backend device and
2140 * also in devices against in codec backend. Checking out device against in
2141 * codec backend or vice versa causes issues.
2142 */
2143 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002144 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002145
2146 /*
2147 * Island cfg and power mode config needs to set before AFE port start.
2148 * Set force routing in case of voice device was enable before.
2149 */
2150
2151 if (uc_info->type == VOICE_CALL &&
2152 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002153 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002154 platform_check_and_update_island_power_status(adev->platform,
2155 uc_info,
2156 snd_device)) {
2157 force_routing = true;
2158 ALOGD("%s:becf: force routing %d for power mode supported device",
2159 __func__, force_routing);
2160 }
2161
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002162 /*
2163 * This function is to make sure that all the active capture usecases
2164 * are always routed to the same input sound device.
2165 * For example, if audio-record and voice-call usecases are currently
2166 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2167 * is received for voice call then we have to make sure that audio-record
2168 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2169 * because of the limitation that two devices cannot be enabled
2170 * at the same time if they share the same backend.
2171 */
2172 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2173 switch_device[i] = false;
2174
2175 list_for_each(node, &adev->usecase_list) {
2176 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302177 /*
2178 * TODO: Enhance below condition to handle BT sco/USB multi recording
2179 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302180
2181 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2182 (usecase->in_snd_device != snd_device || force_routing));
2183 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2184 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2185 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002186 ((backend_check_cond &&
2187 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002188 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002189 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002190 is_single_device_type_equal(&usecase->device_list,
2191 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302192 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002193 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002194 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302195 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002196 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002197 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002198 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002199 switch_device[usecase->id] = true;
2200 num_uc_to_switch++;
2201 }
2202 }
2203
2204 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002205 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002206
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302207 /* Make sure the previous devices to be disabled first and then enable the
2208 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002209 list_for_each(node, &adev->usecase_list) {
2210 usecase = node_to_item(node, struct audio_usecase, list);
2211 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002212 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002213 }
2214 }
2215
2216 list_for_each(node, &adev->usecase_list) {
2217 usecase = node_to_item(node, struct audio_usecase, list);
2218 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002219 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002220 }
2221 }
2222
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002223 /* Re-route all the usecases on the shared backend other than the
2224 specified usecase to new snd devices */
2225 list_for_each(node, &adev->usecase_list) {
2226 usecase = node_to_item(node, struct audio_usecase, list);
2227 /* Update the in_snd_device only before enabling the audio route */
2228 if (switch_device[usecase->id] ) {
2229 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302230 /* Update voc calibration before enabling Voice/VoIP route */
2231 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2232 snd_device_t voip_snd_device;
2233 voip_snd_device = platform_get_output_snd_device(adev->platform,
2234 usecase->stream.out,
2235 usecase->type);
2236 status = platform_switch_voice_call_device_post(adev->platform,
2237 voip_snd_device,
2238 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002239 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302240 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002241 }
2242 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002243 }
2244}
2245
Mingming Yin3a941d42016-02-17 18:08:05 -08002246static void reset_hdmi_sink_caps(struct stream_out *out) {
2247 int i = 0;
2248
2249 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2250 out->supported_channel_masks[i] = 0;
2251 }
2252 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2253 out->supported_formats[i] = 0;
2254 }
2255 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2256 out->supported_sample_rates[i] = 0;
2257 }
2258}
2259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002261static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262{
Mingming Yin3a941d42016-02-17 18:08:05 -08002263 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002264 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2265 out->extconn.cs.controller,
2266 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267
Mingming Yin3a941d42016-02-17 18:08:05 -08002268 reset_hdmi_sink_caps(out);
2269
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002270 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002271 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002272 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002273 out->extconn.cs.stream);
2274 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002275 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002276 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002277 }
2278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002281 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002282 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002283 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2284 case 6:
2285 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2286 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2287 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 break;
2292 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002293 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002294 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295 break;
2296 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002297
2298 // check channel format caps
2299 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002300 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2301 out->extconn.cs.controller,
2302 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002303 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2304 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2305 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2306 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2307 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2308 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2309 }
2310
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002311 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2312 out->extconn.cs.controller,
2313 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002314 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2315 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2316 }
2317
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002318 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2319 out->extconn.cs.controller,
2320 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002321 ALOGV(":%s HDMI supports DTS format", __func__);
2322 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2323 }
2324
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002325 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2326 out->extconn.cs.controller,
2327 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002328 ALOGV(":%s HDMI supports DTS HD format", __func__);
2329 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2330 }
2331
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002332 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2333 out->extconn.cs.controller,
2334 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002335 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2336 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2337 }
2338
Mingming Yin3a941d42016-02-17 18:08:05 -08002339
2340 // check sample rate caps
2341 i = 0;
2342 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002343 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2344 out->extconn.cs.controller,
2345 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002346 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2347 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2348 }
2349 }
2350
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002351 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352}
2353
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002354static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2355 uint32_t *supported_sample_rates __unused,
2356 uint32_t max_rates __unused)
2357{
2358 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2359 supported_sample_rates,
2360 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302361 ssize_t i = 0;
2362
2363 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002364 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2365 supported_sample_rates[i]);
2366 }
2367 return count;
2368}
2369
2370static inline int read_usb_sup_channel_masks(bool is_playback,
2371 audio_channel_mask_t *supported_channel_masks,
2372 uint32_t max_masks)
2373{
2374 int channels = audio_extn_usb_get_max_channels(is_playback);
2375 int channel_count;
2376 uint32_t num_masks = 0;
2377 if (channels > MAX_HIFI_CHANNEL_COUNT)
2378 channels = MAX_HIFI_CHANNEL_COUNT;
2379
2380 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002381 // start from 2 channels as framework currently doesn't support mono.
2382 if (channels >= FCC_2) {
2383 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2384 }
2385 for (channel_count = FCC_2;
2386 channel_count <= channels && num_masks < max_masks;
2387 ++channel_count) {
2388 supported_channel_masks[num_masks++] =
2389 audio_channel_mask_for_index_assignment_from_count(channel_count);
2390 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002391 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002392 // For capture we report all supported channel masks from 1 channel up.
2393 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002394 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2395 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002396 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2397 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2398 if (channel_count <= FCC_2) {
2399 mask = audio_channel_in_mask_from_count(channel_count);
2400 supported_channel_masks[num_masks++] = mask;
2401 }
2402 const audio_channel_mask_t index_mask =
2403 audio_channel_mask_for_index_assignment_from_count(channel_count);
2404 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2405 supported_channel_masks[num_masks++] = index_mask;
2406 }
2407 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002408 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302409
vincenttewf51c94e2019-05-07 10:28:53 +08002410 for (size_t i = 0; i < num_masks; ++i) {
2411 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2412 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302413 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002414 return num_masks;
2415}
2416
2417static inline int read_usb_sup_formats(bool is_playback __unused,
2418 audio_format_t *supported_formats,
2419 uint32_t max_formats __unused)
2420{
2421 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2422 switch (bitwidth) {
2423 case 24:
2424 // XXX : usb.c returns 24 for s24 and s24_le?
2425 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2426 break;
2427 case 32:
2428 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2429 break;
2430 case 16:
2431 default :
2432 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2433 break;
2434 }
2435 ALOGV("%s: %s supported format %d", __func__,
2436 is_playback ? "P" : "C", bitwidth);
2437 return 1;
2438}
2439
2440static inline int read_usb_sup_params_and_compare(bool is_playback,
2441 audio_format_t *format,
2442 audio_format_t *supported_formats,
2443 uint32_t max_formats,
2444 audio_channel_mask_t *mask,
2445 audio_channel_mask_t *supported_channel_masks,
2446 uint32_t max_masks,
2447 uint32_t *rate,
2448 uint32_t *supported_sample_rates,
2449 uint32_t max_rates) {
2450 int ret = 0;
2451 int num_formats;
2452 int num_masks;
2453 int num_rates;
2454 int i;
2455
2456 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2457 max_formats);
2458 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2459 max_masks);
2460
2461 num_rates = read_usb_sup_sample_rates(is_playback,
2462 supported_sample_rates, max_rates);
2463
2464#define LUT(table, len, what, dflt) \
2465 for (i=0; i<len && (table[i] != what); i++); \
2466 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2467
2468 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2469 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2470 LUT(supported_sample_rates, num_rates, *rate, 0);
2471
2472#undef LUT
2473 return ret < 0 ? -EINVAL : 0; // HACK TBD
2474}
2475
Alexy Josephb1379942016-01-29 15:49:38 -08002476audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002477 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002478{
2479 struct audio_usecase *usecase;
2480 struct listnode *node;
2481
2482 list_for_each(node, &adev->usecase_list) {
2483 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002484 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002485 ALOGV("%s: usecase id %d", __func__, usecase->id);
2486 return usecase->id;
2487 }
2488 }
2489 return USECASE_INVALID;
2490}
2491
Alexy Josephb1379942016-01-29 15:49:38 -08002492struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002493 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002494{
2495 struct audio_usecase *usecase;
2496 struct listnode *node;
2497
2498 list_for_each(node, &adev->usecase_list) {
2499 usecase = node_to_item(node, struct audio_usecase, list);
2500 if (usecase->id == uc_id)
2501 return usecase;
2502 }
2503 return NULL;
2504}
2505
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302506/*
2507 * is a true native playback active
2508 */
2509bool audio_is_true_native_stream_active(struct audio_device *adev)
2510{
2511 bool active = false;
2512 int i = 0;
2513 struct listnode *node;
2514
2515 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2516 ALOGV("%s:napb: not in true mode or non hdphones device",
2517 __func__);
2518 active = false;
2519 goto exit;
2520 }
2521
2522 list_for_each(node, &adev->usecase_list) {
2523 struct audio_usecase *uc;
2524 uc = node_to_item(node, struct audio_usecase, list);
2525 struct stream_out *curr_out =
2526 (struct stream_out*) uc->stream.out;
2527
2528 if (curr_out && PCM_PLAYBACK == uc->type) {
2529 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2530 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2531 uc->id, curr_out->sample_rate,
2532 curr_out->bit_width,
2533 platform_get_snd_device_name(uc->out_snd_device));
2534
2535 if (is_offload_usecase(uc->id) &&
2536 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2537 active = true;
2538 ALOGD("%s:napb:native stream detected", __func__);
2539 }
2540 }
2541 }
2542exit:
2543 return active;
2544}
2545
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002546uint32_t adev_get_dsp_bit_width_enforce_mode()
2547{
2548 if (adev == NULL) {
2549 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2550 return 0;
2551 }
2552 return adev->dsp_bit_width_enforce_mode;
2553}
2554
2555static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2556{
2557 char value[PROPERTY_VALUE_MAX];
2558 int trial;
2559 uint32_t dsp_bit_width_enforce_mode = 0;
2560
2561 if (!mixer) {
2562 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2563 __func__);
2564 return 0;
2565 }
2566
2567 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2568 value, NULL) > 0) {
2569 trial = atoi(value);
2570 switch (trial) {
2571 case 16:
2572 dsp_bit_width_enforce_mode = 16;
2573 break;
2574 case 24:
2575 dsp_bit_width_enforce_mode = 24;
2576 break;
2577 case 32:
2578 dsp_bit_width_enforce_mode = 32;
2579 break;
2580 default:
2581 dsp_bit_width_enforce_mode = 0;
2582 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2583 break;
2584 }
2585 }
2586
2587 return dsp_bit_width_enforce_mode;
2588}
2589
2590static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2591 uint32_t enforce_mode,
2592 bool enable)
2593{
2594 struct mixer_ctl *ctl = NULL;
2595 const char *mixer_ctl_name = "ASM Bit Width";
2596 uint32_t asm_bit_width_mode = 0;
2597
2598 if (enforce_mode == 0) {
2599 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2600 return;
2601 }
2602
2603 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2604 if (!ctl) {
2605 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2606 __func__, mixer_ctl_name);
2607 return;
2608 }
2609
2610 if (enable)
2611 asm_bit_width_mode = enforce_mode;
2612 else
2613 asm_bit_width_mode = 0;
2614
2615 ALOGV("%s DSP bit width feature status is %d width=%d",
2616 __func__, enable, asm_bit_width_mode);
2617 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2618 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2619 asm_bit_width_mode);
2620
2621 return;
2622}
2623
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302624/*
2625 * if native DSD playback active
2626 */
2627bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2628{
2629 bool active = false;
2630 struct listnode *node = NULL;
2631 struct audio_usecase *uc = NULL;
2632 struct stream_out *curr_out = NULL;
2633
2634 list_for_each(node, &adev->usecase_list) {
2635 uc = node_to_item(node, struct audio_usecase, list);
2636 curr_out = (struct stream_out*) uc->stream.out;
2637
2638 if (curr_out && PCM_PLAYBACK == uc->type &&
2639 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2640 active = true;
2641 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302642 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302643 }
2644 }
2645 return active;
2646}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302647
2648static bool force_device_switch(struct audio_usecase *usecase)
2649{
2650 bool ret = false;
2651 bool is_it_true_mode = false;
2652
Zhou Song30f2c3e2018-02-08 14:02:15 +08002653 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302654 usecase->type == TRANSCODE_LOOPBACK_RX ||
2655 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002656 return false;
2657 }
2658
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002659 if(usecase->stream.out == NULL) {
2660 ALOGE("%s: stream.out is NULL", __func__);
2661 return false;
2662 }
2663
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302664 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002665 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002666 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2667 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302668 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2669 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2670 (!is_it_true_mode && adev->native_playback_enabled)){
2671 ret = true;
2672 ALOGD("napb: time to toggle native mode");
2673 }
2674 }
2675
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302676 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302677 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2678 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002679 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302680 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302681 ALOGD("Force a2dp device switch to update new encoder config");
2682 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002683 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302684
Florian Pfister1a84f312018-07-19 14:38:18 +02002685 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302686 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2687 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002688 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302689 return ret;
2690}
2691
Aalique Grahame22e49102018-12-18 14:23:57 -08002692static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2693{
2694 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2695}
2696
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302697bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2698{
2699 bool ret=false;
2700 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002701 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2702 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302703 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2704 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002705 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302706 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002707 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2708 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302709 ret = true;
2710
2711 return ret;
2712}
2713
2714bool is_a2dp_device(snd_device_t out_snd_device)
2715{
2716 bool ret=false;
2717 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2718 ret = true;
2719
2720 return ret;
2721}
2722
2723bool is_bt_soc_on(struct audio_device *adev)
2724{
2725 struct mixer_ctl *ctl;
2726 char *mixer_ctl_name = "BT SOC status";
2727 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2728 bool bt_soc_status = true;
2729 if (!ctl) {
2730 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2731 __func__, mixer_ctl_name);
2732 /*This is to ensure we dont break targets which dont have the kernel change*/
2733 return true;
2734 }
2735 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2736 ALOGD("BT SOC status: %d",bt_soc_status);
2737 return bt_soc_status;
2738}
2739
Zhou Song331c8e52019-08-26 14:16:12 +08002740static int configure_btsco_sample_rate(snd_device_t snd_device)
2741{
2742 struct mixer_ctl *ctl = NULL;
2743 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2744 char *rate_str = NULL;
2745 bool is_rx_dev = true;
2746
2747 if (is_btsco_device(snd_device, snd_device)) {
2748 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2749 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2750 if (!ctl_sr_tx || !ctl_sr_rx) {
2751 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2752 if (!ctl_sr)
2753 return -ENOSYS;
2754 }
2755
2756 switch (snd_device) {
2757 case SND_DEVICE_OUT_BT_SCO:
2758 rate_str = "KHZ_8";
2759 break;
2760 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2761 case SND_DEVICE_IN_BT_SCO_MIC:
2762 rate_str = "KHZ_8";
2763 is_rx_dev = false;
2764 break;
2765 case SND_DEVICE_OUT_BT_SCO_WB:
2766 rate_str = "KHZ_16";
2767 break;
2768 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2769 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2770 rate_str = "KHZ_16";
2771 is_rx_dev = false;
2772 break;
2773 default:
2774 return 0;
2775 }
2776
2777 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2778 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2779 return -ENOSYS;
2780 }
2781 return 0;
2782}
2783
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302784int out_standby_l(struct audio_stream *stream);
2785
Eric Laurent637e2d42018-11-15 12:24:31 -08002786struct stream_in *adev_get_active_input(const struct audio_device *adev)
2787{
2788 struct listnode *node;
2789 struct stream_in *last_active_in = NULL;
2790
2791 /* Get last added active input.
2792 * TODO: We may use a priority mechanism to pick highest priority active source */
2793 list_for_each(node, &adev->usecase_list)
2794 {
2795 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2796 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2797 last_active_in = usecase->stream.in;
2798 }
2799
2800 return last_active_in;
2801}
2802
2803struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2804{
2805 struct listnode *node;
2806
2807 /* First check active inputs with voice communication source and then
2808 * any input if audio mode is in communication */
2809 list_for_each(node, &adev->usecase_list)
2810 {
2811 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2812 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2813 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2814 return usecase->stream.in;
2815 }
2816 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2817 return adev_get_active_input(adev);
2818
2819 return NULL;
2820}
2821
Carter Hsu2e429db2019-05-14 18:50:52 +08002822/*
2823 * Aligned with policy.h
2824 */
2825static inline int source_priority(int inputSource)
2826{
2827 switch (inputSource) {
2828 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2829 return 9;
2830 case AUDIO_SOURCE_CAMCORDER:
2831 return 8;
2832 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2833 return 7;
2834 case AUDIO_SOURCE_UNPROCESSED:
2835 return 6;
2836 case AUDIO_SOURCE_MIC:
2837 return 5;
2838 case AUDIO_SOURCE_ECHO_REFERENCE:
2839 return 4;
2840 case AUDIO_SOURCE_FM_TUNER:
2841 return 3;
2842 case AUDIO_SOURCE_VOICE_RECOGNITION:
2843 return 2;
2844 case AUDIO_SOURCE_HOTWORD:
2845 return 1;
2846 default:
2847 break;
2848 }
2849 return 0;
2850}
2851
2852static struct stream_in *get_priority_input(struct audio_device *adev)
2853{
2854 struct listnode *node;
2855 struct audio_usecase *usecase;
2856 int last_priority = 0, priority;
2857 struct stream_in *priority_in = NULL;
2858 struct stream_in *in;
2859
2860 list_for_each(node, &adev->usecase_list) {
2861 usecase = node_to_item(node, struct audio_usecase, list);
2862 if (usecase->type == PCM_CAPTURE) {
2863 in = usecase->stream.in;
2864 if (!in)
2865 continue;
2866 priority = source_priority(in->source);
2867
2868 if (priority > last_priority) {
2869 last_priority = priority;
2870 priority_in = in;
2871 }
2872 }
2873 }
2874 return priority_in;
2875}
2876
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002877int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002879 snd_device_t out_snd_device = SND_DEVICE_NONE;
2880 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002881 struct audio_usecase *usecase = NULL;
2882 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002883 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002884 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302885 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002886 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002887 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302889 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2890
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002891 usecase = get_usecase_from_list(adev, uc_id);
2892 if (usecase == NULL) {
2893 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2894 return -EINVAL;
2895 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002897 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002898 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002899 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002900 (usecase->type == ICC_CALL) ||
2901 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302902 if(usecase->stream.out == NULL) {
2903 ALOGE("%s: stream.out is NULL", __func__);
2904 return -EINVAL;
2905 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002906 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002907 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2908 uc_id);
2909 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2910 uc_id);
2911 } else {
2912 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302913 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002914 in_snd_device = platform_get_input_snd_device(adev->platform,
2915 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302916 &usecase->stream.out->device_list,
2917 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002918 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002919 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302920 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302921 if (usecase->stream.inout == NULL) {
2922 ALOGE("%s: stream.inout is NULL", __func__);
2923 return -EINVAL;
2924 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002925 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302926 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2927 stream_out.format = usecase->stream.inout->out_config.format;
2928 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302929 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002930 assign_devices(&usecase->device_list,
2931 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05302932 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302933 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2934 if (usecase->stream.inout == NULL) {
2935 ALOGE("%s: stream.inout is NULL", __func__);
2936 return -EINVAL;
2937 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302938 struct listnode out_devices;
2939 list_init(&out_devices);
2940 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2941 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002942 assign_devices(&usecase->device_list,
2943 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05302944 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002945 } else {
2946 /*
2947 * If the voice call is active, use the sound devices of voice call usecase
2948 * so that it would not result any device switch. All the usecases will
2949 * be switched to new device when select_devices() is called for voice call
2950 * usecase. This is to avoid switching devices for voice call when
2951 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002952 * choose voice call device only if the use case device is
2953 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002954 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002955 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002956 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002957 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002958 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2959 is_codec_backend_out_device_type(&usecase->device_list)) ||
2960 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2961 is_codec_backend_in_device_type(&usecase->device_list)) ||
2962 is_single_device_type_equal(&vc_usecase->device_list,
2963 AUDIO_DEVICE_OUT_HEARING_AID) ||
2964 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002965 AUDIO_DEVICE_IN_VOICE_CALL) ||
2966 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05302967 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
2968 is_single_device_type_equal(&vc_usecase->device_list,
2969 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
2970 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002971 AUDIO_DEVICE_IN_USB_HEADSET) &&
2972 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302973 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05302974 (is_single_device_type_equal(&usecase->device_list,
2975 AUDIO_DEVICE_IN_USB_HEADSET) &&
2976 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302977 (is_single_device_type_equal(&usecase->device_list,
2978 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2979 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002980 in_snd_device = vc_usecase->in_snd_device;
2981 out_snd_device = vc_usecase->out_snd_device;
2982 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002983 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002984 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002985 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002986 if ((voip_usecase != NULL) &&
2987 (usecase->type == PCM_PLAYBACK) &&
2988 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002989 out_snd_device_backend_match = platform_check_backends_match(
2990 voip_usecase->out_snd_device,
2991 platform_get_output_snd_device(
2992 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302993 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002994 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002995 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2996 (is_codec_backend_out_device_type(&usecase->device_list) ||
2997 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002998 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002999 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003000 in_snd_device = voip_usecase->in_snd_device;
3001 out_snd_device = voip_usecase->out_snd_device;
3002 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003003 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003004 hfp_ucid = audio_extn_hfp_get_usecase();
3005 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003006 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003007 in_snd_device = hfp_usecase->in_snd_device;
3008 out_snd_device = hfp_usecase->out_snd_device;
3009 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003010 }
3011 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303012 if (usecase->stream.out == NULL) {
3013 ALOGE("%s: stream.out is NULL", __func__);
3014 return -EINVAL;
3015 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003016 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003017 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003018 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003019 struct stream_out *voip_out = adev->primary_output;
3020 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003021 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003022 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3023 else
3024 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303025 usecase->stream.out,
3026 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003027 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003028
Eric Laurent637e2d42018-11-15 12:24:31 -08003029 if (voip_usecase)
3030 voip_out = voip_usecase->stream.out;
3031
3032 if (usecase->stream.out == voip_out && voip_in != NULL)
3033 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003034 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003035 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303036 if (usecase->stream.in == NULL) {
3037 ALOGE("%s: stream.in is NULL", __func__);
3038 return -EINVAL;
3039 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003040 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003041 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003042 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003043 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003044 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003045 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003046
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003047 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003048 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003049 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3050 USECASE_AUDIO_PLAYBACK_VOIP);
3051
Carter Hsu2e429db2019-05-14 18:50:52 +08003052 usecase->stream.in->enable_ec_port = false;
3053
Zhou Song503196b2021-07-23 17:31:05 +08003054 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3055 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003056 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003057 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003058 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003059 } else if (adev->primary_output &&
3060 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003061 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003062 } else {
3063 /* forcing speaker o/p device to get matching i/p pair
3064 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003065 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003066 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003067 priority_in = voip_in;
3068 } else {
3069 /* get the input with the highest priority source*/
3070 priority_in = get_priority_input(adev);
3071
Susan Wang727dd6b2021-03-26 11:28:59 -04003072 if (!priority_in ||
3073 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003074 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003075 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003076 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3077 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3078 }
3079 else
3080 in_snd_device = platform_get_input_snd_device(adev->platform,
3081 priority_in,
3082 &out_devices,
3083 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303084 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003085 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003086 }
3087 }
3088
3089 if (out_snd_device == usecase->out_snd_device &&
3090 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303091
3092 if (!force_device_switch(usecase))
3093 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 }
3095
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003096 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003097 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003098 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003099 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3100 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303101 }
3102
Aalique Grahame22e49102018-12-18 14:23:57 -08003103 if (out_snd_device != SND_DEVICE_NONE &&
3104 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3105 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3106 __func__,
3107 use_case_table[uc_id],
3108 adev->last_logged_snd_device[uc_id][0],
3109 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3110 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3111 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3112 -1,
3113 out_snd_device,
3114 platform_get_snd_device_name(out_snd_device),
3115 platform_get_snd_device_acdb_id(out_snd_device));
3116 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3117 }
3118 if (in_snd_device != SND_DEVICE_NONE &&
3119 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3120 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3121 __func__,
3122 use_case_table[uc_id],
3123 adev->last_logged_snd_device[uc_id][1],
3124 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3125 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3126 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3127 -1,
3128 in_snd_device,
3129 platform_get_snd_device_name(in_snd_device),
3130 platform_get_snd_device_acdb_id(in_snd_device));
3131 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3132 }
3133
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 /*
3136 * Limitation: While in call, to do a device switch we need to disable
3137 * and enable both RX and TX devices though one of them is same as current
3138 * device.
3139 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003140 if ((usecase->type == VOICE_CALL) &&
3141 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3142 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003143 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003144 }
3145
3146 if (((usecase->type == VOICE_CALL) ||
3147 (usecase->type == VOIP_CALL)) &&
3148 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3149 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303150 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003151 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003152 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003153
3154 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303155 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003156 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003157 }
3158
Aalique Grahame22e49102018-12-18 14:23:57 -08003159 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3160 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003161 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303162 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003163 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3164 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3165 else
3166 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303167 }
3168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003169 /* Disable current sound devices */
3170 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003171 disable_audio_route(adev, usecase);
3172 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303173 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3174 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 }
3176
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003177 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003178 disable_audio_route(adev, usecase);
3179 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 }
3181
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003182 /* Applicable only on the targets that has external modem.
3183 * New device information should be sent to modem before enabling
3184 * the devices to reduce in-call device switch time.
3185 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003186 if ((usecase->type == VOICE_CALL) &&
3187 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3188 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003189 status = platform_switch_voice_call_enable_device_config(adev->platform,
3190 out_snd_device,
3191 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003192 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003193
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003194 /* Enable new sound devices */
3195 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003196 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303197 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303198 if (platform_check_codec_asrc_support(adev->platform))
3199 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003200 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003201 /* Enable haptics device for haptic usecase */
3202 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3203 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 }
3205
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003206 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303207 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003208 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003209 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003210
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303211 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003212 status = platform_switch_voice_call_device_post(adev->platform,
3213 out_snd_device,
3214 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003215
sangwoo170731f2013-06-08 15:36:36 +09003216 usecase->in_snd_device = in_snd_device;
3217 usecase->out_snd_device = out_snd_device;
3218
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303219 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3220 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303221 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003222 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003223 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003224 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3225 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3226 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3227 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3228 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3229 /*
3230 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3231 * configured device sample rate, if not update the COPP rate to be equal to the
3232 * device sample rate, else open COPP at stream sample rate
3233 */
3234 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3235 usecase->stream.out->sample_rate,
3236 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303237 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303238 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3239 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303240 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003241 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3242 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303243 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3244 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3245 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3246 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3247 }
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003248 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003249 }
3250 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003251
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303252 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3253 struct stream_in *voip_in = get_voice_communication_input(adev);
3254 struct audio_usecase *voip_in_usecase = NULL;
3255 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3256 if (voip_in != NULL &&
3257 voip_in_usecase != NULL &&
3258 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3259 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3260 (voip_in_usecase->in_snd_device ==
3261 platform_get_input_snd_device(adev->platform, voip_in,
3262 &usecase->stream.out->device_list,usecase->type))) {
3263 /*
3264 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3265 * for enabling echo-reference-voip with correct port
3266 */
3267 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3268 disable_audio_route(adev, voip_in_usecase);
3269 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3270 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3271 enable_audio_route(adev, voip_in_usecase);
3272 }
3273 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303274 if (voice_extn_compress_voip_is_active(adev)) {
3275 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3276 USECASE_COMPRESS_VOIP_CALL);
3277 /*
3278 * If only compress voip input is opened voip out will be primary out.
3279 * Need to consider re-routing to select correct i/p pair
3280 */
3281 if ((voip_usecase != NULL) &&
3282 (usecase->type == PCM_PLAYBACK) &&
3283 (usecase->stream.out == voip_usecase->stream.out)) {
3284 in_snd_device = platform_get_input_snd_device(adev->platform,
3285 NULL,
3286 &usecase->stream.out->device_list,
3287 usecase->type);
3288 if (voip_usecase->in_snd_device != in_snd_device ) {
3289 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3290 __func__);
3291 disable_audio_route(adev, voip_usecase);
3292 disable_snd_device(adev, voip_usecase->in_snd_device);
3293 voip_usecase->in_snd_device = in_snd_device;
3294 voip_usecase->out_snd_device = usecase->out_snd_device;
3295 /* Route all TX usecase to Compress voip BE */
3296 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3297 enable_snd_device(adev, in_snd_device);
3298 /* Send Voice related calibration for RX /TX pair */
3299 status = platform_switch_voice_call_device_post(adev->platform,
3300 out_snd_device,
3301 in_snd_device);
3302 enable_audio_route(adev, voip_usecase);
3303 }
3304 }
3305 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303306
3307
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003308 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003309
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003310 /* If input stream is already running then effect needs to be
3311 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003312 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003313 check_and_enable_effect(adev);
3314
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003315 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003316 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303317 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003318 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3319
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003320 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303321 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003322 voice_extn_compress_voip_is_started(adev))
3323 voice_set_sidetone(adev, out_snd_device, true);
3324 }
3325
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003326 /* Applicable only on the targets that has external modem.
3327 * Enable device command should be sent to modem only after
3328 * enabling voice call mixer controls
3329 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003330 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003331 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3332 out_snd_device,
3333 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303334
3335 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003336 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303337 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003338 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303339 if (is_bt_soc_on(adev) == false){
3340 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003341 if (in->pcm != NULL)
3342 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303343 }
3344 }
3345 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3346 && usecase->stream.out->started) {
3347 if (is_bt_soc_on(adev) == false) {
3348 ALOGD("BT SCO/A2DP disconnected while in connection");
3349 out_standby_l(&usecase->stream.out->stream.common);
3350 }
3351 }
3352 } else if ((usecase->stream.out != NULL) &&
3353 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303354 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3355 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003356 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303357 usecase->stream.out->started) {
3358 if (is_bt_soc_on(adev) == false) {
3359 ALOGD("BT SCO/A2dp disconnected while in connection");
3360 out_standby_l(&usecase->stream.out->stream.common);
3361 }
3362 }
3363 }
3364
Yung Ti Su70cb8242018-06-22 17:38:47 +08003365 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003366 struct stream_out *voip_out = voip_usecase->stream.out;
3367 audio_extn_utils_send_app_type_gain(adev,
3368 voip_out->app_type_cfg.app_type,
3369 &voip_out->app_type_cfg.gain[0]);
3370 }
3371
Ajender Reddyb940b832021-07-07 11:51:42 +05303372 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 return status;
3375}
3376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377static int stop_input_stream(struct stream_in *in)
3378{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303379 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303381
3382 if (in == NULL) {
3383 ALOGE("%s: stream_in ptr is NULL", __func__);
3384 return -EINVAL;
3385 }
3386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003388 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389
Eric Laurent994a6932013-07-17 11:51:42 -07003390 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003391 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 uc_info = get_usecase_from_list(adev, in->usecase);
3393 if (uc_info == NULL) {
3394 ALOGE("%s: Could not find the usecase (%d) in the list",
3395 __func__, in->usecase);
3396 return -EINVAL;
3397 }
3398
Carter Hsu2e429db2019-05-14 18:50:52 +08003399 priority_in = get_priority_input(adev);
3400
Derek Chenea197282019-01-07 17:35:01 -08003401 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3402 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003403
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003404 /* Close in-call recording streams */
3405 voice_check_and_stop_incall_rec_usecase(adev, in);
3406
Eric Laurent150dbfe2013-02-27 14:31:02 -08003407 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003408 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003409
3410 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003411 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003413 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303414 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3415
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003416 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303417 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003418 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419
Carter Hsu2e429db2019-05-14 18:50:52 +08003420 if (priority_in == in) {
3421 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303422 if (priority_in) {
3423 if (is_usb_in_device_type(&priority_in->device_list)) {
3424 if (audio_extn_usb_connected(NULL))
3425 select_devices(adev, priority_in->usecase);
3426 } else {
3427 select_devices(adev, priority_in->usecase);
3428 }
3429 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003430 }
3431
Vatsal Buchac09ae062018-11-14 13:25:08 +05303432 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003433 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 return ret;
3435}
3436
3437int start_input_stream(struct stream_in *in)
3438{
3439 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003440 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303442
3443 if (in == NULL) {
3444 ALOGE("%s: stream_in ptr is NULL", __func__);
3445 return -EINVAL;
3446 }
3447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003449 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003450 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451
Mingming Yin2664a5b2015-09-03 10:53:11 -07003452 if (get_usecase_from_list(adev, usecase) == NULL)
3453 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303454 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3455 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003456
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303457 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003458 CARD_STATUS_OFFLINE == adev->card_status ||
3459 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3460 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303461 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303462 goto error_config;
3463 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303464
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003465 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303466 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303467 ALOGE("%s: SCO profile is not ready, return error", __func__);
3468 ret = -EIO;
3469 goto error_config;
3470 }
3471 }
3472
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003473 /* Check if source matches incall recording usecase criteria */
3474 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3475 if (ret)
3476 goto error_config;
3477 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003478 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3479
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303480 if (audio_extn_cin_attached_usecase(in))
3481 audio_extn_cin_acquire_usecase(in);
3482
Mingming Yin2664a5b2015-09-03 10:53:11 -07003483 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3484 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3485 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003486 ret = -EINVAL;
3487 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003488 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003489
Eric Laurentb23d5282013-05-14 15:27:20 -07003490 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 if (in->pcm_device_id < 0) {
3492 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3493 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003494 ret = -EINVAL;
3495 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003499
3500 if (!uc_info) {
3501 ret = -ENOMEM;
3502 goto error_config;
3503 }
3504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 uc_info->id = in->usecase;
3506 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003507 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003508 list_init(&uc_info->device_list);
3509 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003510 uc_info->in_snd_device = SND_DEVICE_NONE;
3511 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003513 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003514 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303515 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3516 adev->perf_lock_opts,
3517 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003518 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
Derek Chenea197282019-01-07 17:35:01 -08003520 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3521 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003522
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303523 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3524
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303525 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303526 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303527 if (ret)
3528 goto error_open;
3529 else
3530 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003531 }
3532
Haynes Mathew George16081042017-05-31 17:16:49 -07003533 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003534 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003535 ALOGE("%s: pcm stream not ready", __func__);
3536 goto error_open;
3537 }
3538 ret = pcm_start(in->pcm);
3539 if (ret < 0) {
3540 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3541 goto error_open;
3542 }
3543 } else {
3544 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3545 unsigned int pcm_open_retry_count = 0;
3546
Zhou Song62ea0282020-03-22 19:53:01 +08003547 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3548 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003549 flags |= PCM_MMAP | PCM_NOIRQ;
3550 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3551 } else if (in->realtime) {
3552 flags |= PCM_MMAP | PCM_NOIRQ;
3553 }
3554
Garmond Leunge2433c32017-09-28 21:51:22 -07003555 if (audio_extn_ffv_get_stream() == in) {
3556 ALOGD("%s: ffv stream, update pcm config", __func__);
3557 audio_extn_ffv_update_pcm_config(&config);
3558 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003559 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3560 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3561
3562 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003563 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003564 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003565 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003566 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303567 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303568 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3569 adev->card_status = CARD_STATUS_OFFLINE;
3570 in->card_status = CARD_STATUS_OFFLINE;
3571 ret = -EIO;
3572 goto error_open;
3573 }
3574
Haynes Mathew George16081042017-05-31 17:16:49 -07003575 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3576 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3577 if (in->pcm != NULL) {
3578 pcm_close(in->pcm);
3579 in->pcm = NULL;
3580 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003581 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003582 ret = -EIO;
3583 goto error_open;
3584 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003585 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003586 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3587 continue;
3588 }
3589 break;
3590 }
3591
3592 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003593 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003594 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003595 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003596 if (ret < 0) {
3597 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3598 pcm_close(in->pcm);
3599 in->pcm = NULL;
3600 goto error_open;
3601 }
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303602 if (in->flags == AUDIO_INPUT_FLAG_FAST)
3603 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003604 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003605 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003606 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003607 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003608 if (ret < 0) {
3609 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003610 pcm_close(in->pcm);
3611 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003612 goto error_open;
3613 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003614 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003615 }
3616
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003617 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003618 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3619 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003620
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003621 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303622 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3623
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303624done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003625 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303626 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303627 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303628 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003629 return ret;
3630
3631error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003632 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303633 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003635
Eric Laurentc8400632013-02-14 19:04:54 -08003636error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003637 if (audio_extn_cin_attached_usecase(in))
3638 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303639 /*
3640 * sleep 50ms to allow sufficient time for kernel
3641 * drivers to recover incases like SSR.
3642 */
3643 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003644 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303645 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003646 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647}
3648
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003649void lock_input_stream(struct stream_in *in)
3650{
3651 pthread_mutex_lock(&in->pre_lock);
3652 pthread_mutex_lock(&in->lock);
3653 pthread_mutex_unlock(&in->pre_lock);
3654}
3655
3656void lock_output_stream(struct stream_out *out)
3657{
3658 pthread_mutex_lock(&out->pre_lock);
3659 pthread_mutex_lock(&out->lock);
3660 pthread_mutex_unlock(&out->pre_lock);
3661}
3662
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663/* must be called with out->lock locked */
3664static int send_offload_cmd_l(struct stream_out* out, int command)
3665{
3666 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3667
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003668 if (!cmd) {
3669 ALOGE("failed to allocate mem for command 0x%x", command);
3670 return -ENOMEM;
3671 }
3672
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 ALOGVV("%s %d", __func__, command);
3674
3675 cmd->cmd = command;
3676 list_add_tail(&out->offload_cmd_list, &cmd->node);
3677 pthread_cond_signal(&out->offload_cond);
3678 return 0;
3679}
3680
Gautam Manam14c198b2020-12-24 14:08:04 +05303681/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682static void stop_compressed_output_l(struct stream_out *out)
3683{
Gautam Manam14c198b2020-12-24 14:08:04 +05303684 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003685 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303686 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003687
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003689 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003690 if (out->compr != NULL) {
3691 compress_stop(out->compr);
3692 while (out->offload_thread_blocked) {
3693 pthread_cond_wait(&out->cond, &out->lock);
3694 }
3695 }
3696}
3697
Varun Balaraje49253e2017-07-06 19:48:56 +05303698bool is_interactive_usecase(audio_usecase_t uc_id)
3699{
3700 unsigned int i;
3701 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3702 if (uc_id == interactive_usecases[i])
3703 return true;
3704 }
3705 return false;
3706}
3707
3708static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3709{
3710 audio_usecase_t ret_uc = USECASE_INVALID;
3711 unsigned int intract_uc_index;
3712 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3713
3714 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3715 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3716 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3717 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3718 ret_uc = interactive_usecases[intract_uc_index];
3719 break;
3720 }
3721 }
3722
3723 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3724 return ret_uc;
3725}
3726
3727static void free_interactive_usecase(struct audio_device *adev,
3728 audio_usecase_t uc_id)
3729{
3730 unsigned int interact_uc_index;
3731 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3732
3733 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3734 if (interactive_usecases[interact_uc_index] == uc_id) {
3735 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3736 break;
3737 }
3738 }
3739 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3740}
3741
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003742bool is_offload_usecase(audio_usecase_t uc_id)
3743{
3744 unsigned int i;
3745 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3746 if (uc_id == offload_usecases[i])
3747 return true;
3748 }
3749 return false;
3750}
3751
Dhananjay Kumarac341582017-02-23 23:42:25 +05303752static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003753{
vivek mehta446c3962015-09-14 10:57:35 -07003754 audio_usecase_t ret_uc = USECASE_INVALID;
3755 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003756 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003757 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303758 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003759 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3760 else
3761 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003762
vivek mehta446c3962015-09-14 10:57:35 -07003763 pthread_mutex_lock(&adev->lock);
3764 if (get_usecase_from_list(adev, ret_uc) != NULL)
3765 ret_uc = USECASE_INVALID;
3766 pthread_mutex_unlock(&adev->lock);
3767
3768 return ret_uc;
3769 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003770
3771 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003772 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3773 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3774 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3775 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003776 break;
3777 }
3778 }
vivek mehta446c3962015-09-14 10:57:35 -07003779
3780 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3781 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003782}
3783
3784static void free_offload_usecase(struct audio_device *adev,
3785 audio_usecase_t uc_id)
3786{
vivek mehta446c3962015-09-14 10:57:35 -07003787 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003788 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003789
3790 if (!adev->multi_offload_enable)
3791 return;
3792
3793 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3794 if (offload_usecases[offload_uc_index] == uc_id) {
3795 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003796 break;
3797 }
3798 }
3799 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3800}
3801
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802static void *offload_thread_loop(void *context)
3803{
3804 struct stream_out *out = (struct stream_out *) context;
3805 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003806 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003807
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003808 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003809 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003810 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3811
3812 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003813 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003814 out->offload_state = OFFLOAD_STATE_IDLE;
3815 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003816 for (;;) {
3817 struct offload_cmd *cmd = NULL;
3818 stream_callback_event_t event;
3819 bool send_callback = false;
3820
3821 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3822 __func__, list_empty(&out->offload_cmd_list),
3823 out->offload_state);
3824 if (list_empty(&out->offload_cmd_list)) {
3825 ALOGV("%s SLEEPING", __func__);
3826 pthread_cond_wait(&out->offload_cond, &out->lock);
3827 ALOGV("%s RUNNING", __func__);
3828 continue;
3829 }
3830
3831 item = list_head(&out->offload_cmd_list);
3832 cmd = node_to_item(item, struct offload_cmd, node);
3833 list_remove(item);
3834
3835 ALOGVV("%s STATE %d CMD %d out->compr %p",
3836 __func__, out->offload_state, cmd->cmd, out->compr);
3837
3838 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3839 free(cmd);
3840 break;
3841 }
3842
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003843 // allow OFFLOAD_CMD_ERROR reporting during standby
3844 // this is needed to handle failures during compress_open
3845 // Note however that on a pause timeout, the stream is closed
3846 // and no offload usecase will be active. Therefore this
3847 // special case is needed for compress_open failures alone
3848 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3849 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003851 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003852 pthread_cond_signal(&out->cond);
3853 continue;
3854 }
3855 out->offload_thread_blocked = true;
3856 pthread_mutex_unlock(&out->lock);
3857 send_callback = false;
3858 switch(cmd->cmd) {
3859 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003860 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003861 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003862 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003863 send_callback = true;
3864 event = STREAM_CBK_EVENT_WRITE_READY;
3865 break;
3866 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003867 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303868 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003869 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303870 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003871 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303872 if (ret < 0)
3873 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303874 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303875 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003876 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003877 else
3878 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003879 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003880 (CARD_STATUS_OFFLINE == out->card_status ||
3881 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303882 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303883 pthread_mutex_lock(&out->lock);
3884 out->send_new_metadata = 1;
3885 out->send_next_track_params = true;
3886 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303887 event = STREAM_CBK_EVENT_DRAIN_READY;
3888 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3889 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303890 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003891 break;
3892 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003893 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003894 ret = compress_drain(out->compr);
3895 ALOGD("copl(%p):out of compress_drain", out);
3896 // EINTR check avoids drain interruption due to SSR
3897 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003898 (CARD_STATUS_OFFLINE == out->card_status ||
3899 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003900 send_callback = true;
3901 event = STREAM_CBK_EVENT_DRAIN_READY;
3902 } else
3903 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003904 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303905 case OFFLOAD_CMD_ERROR:
3906 ALOGD("copl(%p): sending error callback to AF", out);
3907 send_callback = true;
3908 event = STREAM_CBK_EVENT_ERROR;
3909 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910 default:
3911 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3912 break;
3913 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003914 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003915 out->offload_thread_blocked = false;
3916 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003917 if (send_callback && out->client_callback) {
3918 ALOGVV("%s: sending client_callback event %d", __func__, event);
3919 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003920 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003921 free(cmd);
3922 }
3923
3924 pthread_cond_signal(&out->cond);
3925 while (!list_empty(&out->offload_cmd_list)) {
3926 item = list_head(&out->offload_cmd_list);
3927 list_remove(item);
3928 free(node_to_item(item, struct offload_cmd, node));
3929 }
3930 pthread_mutex_unlock(&out->lock);
3931
3932 return NULL;
3933}
3934
3935static int create_offload_callback_thread(struct stream_out *out)
3936{
3937 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3938 list_init(&out->offload_cmd_list);
3939 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3940 offload_thread_loop, out);
3941 return 0;
3942}
3943
3944static int destroy_offload_callback_thread(struct stream_out *out)
3945{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003946 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003947 stop_compressed_output_l(out);
3948 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3949
3950 pthread_mutex_unlock(&out->lock);
3951 pthread_join(out->offload_thread, (void **) NULL);
3952 pthread_cond_destroy(&out->offload_cond);
3953
3954 return 0;
3955}
3956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957static int stop_output_stream(struct stream_out *out)
3958{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303959 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 struct audio_usecase *uc_info;
3961 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003962 bool has_voip_usecase =
3963 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964
Eric Laurent994a6932013-07-17 11:51:42 -07003965 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003966 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967 uc_info = get_usecase_from_list(adev, out->usecase);
3968 if (uc_info == NULL) {
3969 ALOGE("%s: Could not find the usecase (%d) in the list",
3970 __func__, out->usecase);
3971 return -EINVAL;
3972 }
3973
Zhou Songbaddf9f2020-11-20 13:57:39 +08003974 out->a2dp_muted = false;
3975
Derek Chenea197282019-01-07 17:35:01 -08003976 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3977 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003978
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003979 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303980 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003981 if (adev->visualizer_stop_output != NULL)
3982 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003983
3984 audio_extn_dts_remove_state_notifier_node(out->usecase);
3985
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003986 if (adev->offload_effects_stop_output != NULL)
3987 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003988 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3989 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3990 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003991 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003992
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003993 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3994 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003995 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003996 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003997
Eric Laurent150dbfe2013-02-27 14:31:02 -08003998 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003999 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004000
4001 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004002 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004003 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4004 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005
Aalique Grahame22e49102018-12-18 14:23:57 -08004006 audio_extn_extspk_update(adev->extspk);
4007
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004008 if (is_offload_usecase(out->usecase)) {
4009 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4010 adev->dsp_bit_width_enforce_mode,
4011 false);
4012 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004013 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004014 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4015 false);
4016
4017 if (ret != 0)
4018 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4019 /* default service interval was successfully updated,
4020 reopen USB backend with new service interval */
4021 ret = 0;
4022 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004023
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004024 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304025 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004026 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304027 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004028 ALOGV("Disable passthrough , reset mixer to pcm");
4029 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004030#ifdef AUDIO_GKI_ENABLED
4031 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4032 out->compr_config.codec->reserved[0] = 0;
4033#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004034 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004035#endif
Mingming Yin21854652016-04-13 11:54:02 -07004036 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004037 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4038 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004039
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304040 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004041 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304042 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304043
Manish Dewangan21a850a2017-08-14 12:03:55 +05304044 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004045 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4046 if (ret < 0)
4047 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4048 }
4049
Zhou Song642ec432020-12-23 16:11:10 +08004050 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004051 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004052 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004053 struct listnode *node;
4054 struct audio_usecase *usecase;
4055 list_for_each(node, &adev->usecase_list) {
4056 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004057 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4058 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304059 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004060 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004061 continue;
4062
4063 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4064 __func__, usecase->id, use_case_table[usecase->id],
4065 out->usecase, use_case_table[out->usecase]);
4066 select_devices(adev, usecase->id);
4067 }
4068 }
4069
Zhenlin Lian4f947842022-05-14 15:50:52 +05304070 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004071 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004072 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073 return ret;
4074}
4075
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004076struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4077 unsigned int flags, unsigned int pcm_open_retry_count,
4078 struct pcm_config *config)
4079{
4080 struct pcm* pcm = NULL;
4081
4082 while (1) {
4083 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4084 if (pcm == NULL || !pcm_is_ready(pcm)) {
4085 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4086 if (pcm != NULL) {
4087 pcm_close(pcm);
4088 pcm = NULL;
4089 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004090 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004091 return NULL;
4092
Weiyin Jiang72197252019-10-09 11:49:32 +08004093 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004094 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4095 continue;
4096 }
4097 break;
4098 }
4099
4100 if (pcm_is_ready(pcm)) {
4101 int ret = pcm_prepare(pcm);
4102 if (ret < 0) {
4103 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4104 pcm_close(pcm);
4105 pcm = NULL;
4106 }
4107 }
4108
4109 return pcm;
4110}
4111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112int start_output_stream(struct stream_out *out)
4113{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115 struct audio_usecase *uc_info;
4116 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004117 char mixer_ctl_name[128];
4118 struct mixer_ctl *ctl = NULL;
4119 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304120 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004121 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122
Haynes Mathew George380745d2017-10-04 15:27:45 -07004123 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004124 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4125 ret = -EINVAL;
4126 goto error_config;
4127 }
4128
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004129 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304130 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004131 get_device_types(&out->device_list), is_haptic_usecase);
4132
4133 bool is_speaker_active = compare_device_type(&out->device_list,
4134 AUDIO_DEVICE_OUT_SPEAKER);
4135 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4136 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304137
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304138 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004139 CARD_STATUS_OFFLINE == adev->card_status ||
4140 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304141 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304142 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004143 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304144 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304145
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004146 //Update incall music usecase to reflect correct voice session
4147 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4148 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4149 if (ret != 0) {
4150 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4151 __func__, ret);
4152 goto error_config;
4153 }
4154 }
4155
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004156 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004157 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004158 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304159 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304160 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004161 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304162 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4163 ret = -EAGAIN;
4164 goto error_config;
4165 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304166 }
4167 }
4168 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004169 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304170 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004171 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304172 //combo usecase just by pass a2dp
4173 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004174 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304175 } else {
4176 ALOGE("%s: SCO profile is not ready, return error", __func__);
4177 ret = -EAGAIN;
4178 goto error_config;
4179 }
4180 }
4181 }
4182
Eric Laurentb23d5282013-05-14 15:27:20 -07004183 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 if (out->pcm_device_id < 0) {
4185 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4186 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004187 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004188 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189 }
4190
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004191 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004192 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4193 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004194 if (adev->haptic_pcm_device_id < 0) {
4195 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4196 __func__, adev->haptic_pcm_device_id, out->usecase);
4197 ret = -EINVAL;
4198 goto error_config;
4199 }
4200 }
4201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004203
4204 if (!uc_info) {
4205 ret = -ENOMEM;
4206 goto error_config;
4207 }
4208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 uc_info->id = out->usecase;
4210 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004211 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004212 list_init(&uc_info->device_list);
4213 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004214 uc_info->in_snd_device = SND_DEVICE_NONE;
4215 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004216
4217 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004218 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004219 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4220 /* USB backend is not reopened immediately.
4221 This is eventually done as part of select_devices */
4222 }
4223
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004224 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225
Wei Wangf7ca6c92017-11-21 14:51:20 -08004226 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304227 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4228 adev->perf_lock_opts,
4229 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304230
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004231 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304232 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304233 if (audio_extn_passthru_is_enabled() &&
4234 audio_extn_passthru_is_passthrough_stream(out)) {
4235 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304236 }
4237 }
4238
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004239 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004240 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304241 if (!a2dp_combo) {
4242 check_a2dp_restore_l(adev, out, false);
4243 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004244 struct listnode dev;
4245 list_init(&dev);
4246 assign_devices(&dev, &out->device_list);
4247 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4248 reassign_device_list(&out->device_list,
4249 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004250 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004251 reassign_device_list(&out->device_list,
4252 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304253 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004254 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304255 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304256 }
4257 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304258 select_devices(adev, out->usecase);
4259 if (is_a2dp_out_device_type(&out->device_list) &&
4260 !adev->a2dp_started) {
4261 if (is_speaker_active || is_speaker_safe_active) {
4262 struct listnode dev;
4263 list_init(&dev);
4264 assign_devices(&dev, &out->device_list);
4265 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4266 reassign_device_list(&out->device_list,
4267 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4268 else
4269 reassign_device_list(&out->device_list,
4270 AUDIO_DEVICE_OUT_SPEAKER, "");
4271 select_devices(adev, out->usecase);
4272 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304273 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304274 } else {
4275 ret = -EINVAL;
4276 goto error_open;
4277 }
4278 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304279 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004280
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004281 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4282 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004283 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004284 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004285
Derek Chenea197282019-01-07 17:35:01 -08004286 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4287 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004288
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004289 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4290 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004291
4292 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004293 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004294 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4295 ALOGE("%s: pcm stream not ready", __func__);
4296 goto error_open;
4297 }
4298 ret = pcm_start(out->pcm);
4299 if (ret < 0) {
4300 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4301 goto error_open;
4302 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004303 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004304 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004305 unsigned int flags = PCM_OUT;
4306 unsigned int pcm_open_retry_count = 0;
4307 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4308 flags |= PCM_MMAP | PCM_NOIRQ;
4309 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004310 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004311 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004312 } else
4313 flags |= PCM_MONOTONIC;
4314
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004315 if ((adev->vr_audio_mode_enabled) &&
4316 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4317 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4318 "PCM_Dev %d Topology", out->pcm_device_id);
4319 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4320 if (!ctl) {
4321 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4322 __func__, mixer_ctl_name);
4323 } else {
4324 //if success use ULLPP
4325 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4326 __func__, mixer_ctl_name, out->pcm_device_id);
4327 //There is a still a possibility that some sessions
4328 // that request for FAST|RAW when 3D audio is active
4329 //can go through ULLPP. Ideally we expects apps to
4330 //listen to audio focus and stop concurrent playback
4331 //Also, we will look for mode flag (voice_in_communication)
4332 //before enabling the realtime flag.
4333 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4334 }
4335 }
4336
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304337 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4338 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304339
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004340 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4341 flags, pcm_open_retry_count,
4342 &(out->config));
4343 if (out->pcm == NULL) {
4344 ret = -EIO;
4345 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004346 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004347
4348 if (is_haptic_usecase) {
4349 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4350 adev->haptic_pcm_device_id,
4351 flags, pcm_open_retry_count,
4352 &(adev->haptics_config));
4353 // failure to open haptics pcm shouldnt stop audio,
4354 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004355
4356 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4357 ALOGD("%s: enable haptic audio synchronization", __func__);
4358 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4359 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004360 }
4361
Zhou Song2b8f28f2017-09-11 10:51:38 +08004362 // apply volume for voip playback after path is set up
4363 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4364 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304365 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4366 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304367 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4368 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004369 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4370 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304371#ifdef SOFT_VOLUME
4372 out_set_soft_volume_params(&out->stream);
4373#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304374 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004375 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004376 /*
4377 * set custom channel map if:
4378 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4379 * 2. custom channel map has been set by client
4380 * else default channel map of FC/FR/FL can always be set to DSP
4381 */
4382 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4383 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004384 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004385 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4386 adev->dsp_bit_width_enforce_mode,
4387 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004389 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004390 out->compr = compress_open(adev->snd_card,
4391 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004392 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004393 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304394 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304395 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4396 adev->card_status = CARD_STATUS_OFFLINE;
4397 out->card_status = CARD_STATUS_OFFLINE;
4398 ret = -EIO;
4399 goto error_open;
4400 }
4401
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004402 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004403 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004404 compress_close(out->compr);
4405 out->compr = NULL;
4406 ret = -EIO;
4407 goto error_open;
4408 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304409 /* compress_open sends params of the track, so reset the flag here */
4410 out->is_compr_metadata_avail = false;
4411
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004412 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004413 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004414
Fred Oh3f43e742015-03-04 18:42:34 -08004415 /* Since small bufs uses blocking writes, a write will be blocked
4416 for the default max poll time (20s) in the event of an SSR.
4417 Reduce the poll time to observe and deal with SSR faster.
4418 */
Ashish Jain5106d362016-05-11 19:23:33 +05304419 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004420 compress_set_max_poll_wait(out->compr, 1000);
4421 }
4422
Manish Dewangan69426c82017-01-30 17:35:36 +05304423 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304424 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304425
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004426 audio_extn_dts_create_state_notifier_node(out->usecase);
4427 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4428 popcount(out->channel_mask),
4429 out->playback_started);
4430
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004431#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304432 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004433 audio_extn_dolby_send_ddp_endp_params(adev);
4434#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304435 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4436 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004437 if (adev->visualizer_start_output != NULL)
4438 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4439 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304440 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004441 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004442 }
Derek Chenf13dd492018-11-13 14:53:51 -08004443
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004444 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004445 /* Update cached volume from media to offload/direct stream */
4446 struct listnode *node = NULL;
4447 list_for_each(node, &adev->active_outputs_list) {
4448 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4449 streams_output_ctxt_t,
4450 list);
4451 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4452 out->volume_l = out_ctxt->output->volume_l;
4453 out->volume_r = out_ctxt->output->volume_r;
4454 }
4455 }
4456 out_set_compr_volume(&out->stream,
4457 out->volume_l, out->volume_r);
4458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004460
4461 if (ret == 0) {
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304462 if (out->flags == AUDIO_OUTPUT_FLAG_FAST)
4463 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004464 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004465 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4466 ALOGE("%s: pcm stream not ready", __func__);
4467 goto error_open;
4468 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004469 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004470 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004471 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004472 if (ret < 0)
4473 goto error_open;
4474 }
4475 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004476 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304477 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304478 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004479
vivek mehtad15d2bf2019-05-17 13:35:10 -07004480 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4481 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4482 audio_low_latency_hint_start();
4483 }
4484
Manish Dewangan21a850a2017-08-14 12:03:55 +05304485 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004486 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004487 if (ret < 0)
4488 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4489 }
4490
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004491 // consider a scenario where on pause lower layers are tear down.
4492 // so on resume, swap mixer control need to be sent only when
4493 // backend is active, hence rather than sending from enable device
4494 // sending it from start of streamtream
4495
4496 platform_set_swap_channels(adev, true);
4497
Haynes Mathew George380745d2017-10-04 15:27:45 -07004498 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304499 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004500 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004501error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004502 if (adev->haptic_pcm) {
4503 pcm_close(adev->haptic_pcm);
4504 adev->haptic_pcm = NULL;
4505 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004506 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304507 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004509error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304510 /*
4511 * sleep 50ms to allow sufficient time for kernel
4512 * drivers to recover incases like SSR.
4513 */
4514 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004515error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004516 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304517 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004518 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519}
4520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521static int check_input_parameters(uint32_t sample_rate,
4522 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004523 int channel_count,
4524 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004526 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304528 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4529 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4530 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004531 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004532 !audio_extn_compr_cap_format_supported(format) &&
4533 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004534 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004535
Aalique Grahame22e49102018-12-18 14:23:57 -08004536 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4537 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4538 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4539 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4540 return -EINVAL;
4541 }
4542
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004543 switch (channel_count) {
4544 case 1:
4545 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304546 case 3:
4547 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004548 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004549 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304550 case 10:
4551 case 12:
4552 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004553 break;
4554 default:
4555 ret = -EINVAL;
4556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557
4558 switch (sample_rate) {
4559 case 8000:
4560 case 11025:
4561 case 12000:
4562 case 16000:
4563 case 22050:
4564 case 24000:
4565 case 32000:
4566 case 44100:
4567 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004568 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304569 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004570 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304571 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 break;
4573 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004574 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575 }
4576
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004577 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578}
4579
Naresh Tanniru04f71882018-06-26 17:46:22 +05304580
4581/** Add a value in a list if not already present.
4582 * @return true if value was successfully inserted or already present,
4583 * false if the list is full and does not contain the value.
4584 */
4585static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4586 for (size_t i = 0; i < list_length; i++) {
4587 if (list[i] == value) return true; // value is already present
4588 if (list[i] == 0) { // no values in this slot
4589 list[i] = value;
4590 return true; // value inserted
4591 }
4592 }
4593 return false; // could not insert value
4594}
4595
4596/** Add channel_mask in supported_channel_masks if not already present.
4597 * @return true if channel_mask was successfully inserted or already present,
4598 * false if supported_channel_masks is full and does not contain channel_mask.
4599 */
4600static void register_channel_mask(audio_channel_mask_t channel_mask,
4601 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4602 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4603 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4604}
4605
4606/** Add format in supported_formats if not already present.
4607 * @return true if format was successfully inserted or already present,
4608 * false if supported_formats is full and does not contain format.
4609 */
4610static void register_format(audio_format_t format,
4611 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4612 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4613 "%s: stream can not declare supporting its format %x", __func__, format);
4614}
4615/** Add sample_rate in supported_sample_rates if not already present.
4616 * @return true if sample_rate was successfully inserted or already present,
4617 * false if supported_sample_rates is full and does not contain sample_rate.
4618 */
4619static void register_sample_rate(uint32_t sample_rate,
4620 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4621 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4622 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4623}
4624
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004625static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4626{
4627 uint32_t high = num1, low = num2, temp = 0;
4628
4629 if (!num1 || !num2)
4630 return 0;
4631
4632 if (num1 < num2) {
4633 high = num2;
4634 low = num1;
4635 }
4636
4637 while (low != 0) {
4638 temp = low;
4639 low = high % low;
4640 high = temp;
4641 }
4642 return (num1 * num2)/high;
4643}
4644
4645static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4646{
4647 uint32_t remainder = 0;
4648
4649 if (!multiplier)
4650 return num;
4651
4652 remainder = num % multiplier;
4653 if (remainder)
4654 num += (multiplier - remainder);
4655
4656 return num;
4657}
4658
Aalique Grahame22e49102018-12-18 14:23:57 -08004659static size_t get_stream_buffer_size(size_t duration_ms,
4660 uint32_t sample_rate,
4661 audio_format_t format,
4662 int channel_count,
4663 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664{
4665 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004666 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667
Aalique Grahame22e49102018-12-18 14:23:57 -08004668 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304669 if (is_low_latency){
4670 switch(sample_rate) {
4671 case 48000:
4672 size = 240;
4673 break;
4674 case 32000:
4675 size = 160;
4676 break;
4677 case 24000:
4678 size = 120;
4679 break;
4680 case 16000:
4681 size = 80;
4682 break;
4683 case 8000:
4684 size = 40;
4685 break;
4686 default:
4687 size = 240;
4688 }
4689 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304690
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004691 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004692 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693
Ralf Herzbd08d632018-09-28 15:50:49 +02004694 /* make sure the size is multiple of 32 bytes and additionally multiple of
4695 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004696 * At 48 kHz mono 16-bit PCM:
4697 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4698 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004699 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004700 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004701 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004702
4703 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704}
4705
Aalique Grahame22e49102018-12-18 14:23:57 -08004706static size_t get_input_buffer_size(uint32_t sample_rate,
4707 audio_format_t format,
4708 int channel_count,
4709 bool is_low_latency)
4710{
4711 /* Don't know if USB HIFI in this context so use true to be conservative */
4712 if (check_input_parameters(sample_rate, format, channel_count,
4713 true /*is_usb_hifi */) != 0)
4714 return 0;
4715
4716 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4717 sample_rate,
4718 format,
4719 channel_count,
4720 is_low_latency);
4721}
4722
Derek Chenf6318be2017-06-12 17:16:24 -04004723size_t get_output_period_size(uint32_t sample_rate,
4724 audio_format_t format,
4725 int channel_count,
4726 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304727{
4728 size_t size = 0;
4729 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4730
4731 if ((duration == 0) || (sample_rate == 0) ||
4732 (bytes_per_sample == 0) || (channel_count == 0)) {
4733 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4734 bytes_per_sample, channel_count);
4735 return -EINVAL;
4736 }
4737
4738 size = (sample_rate *
4739 duration *
4740 bytes_per_sample *
4741 channel_count) / 1000;
4742 /*
4743 * To have same PCM samples for all channels, the buffer size requires to
4744 * be multiple of (number of channels * bytes per sample)
4745 * For writes to succeed, the buffer must be written at address which is multiple of 32
4746 */
4747 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4748
4749 return (size/(channel_count * bytes_per_sample));
4750}
4751
Zhou Song48453a02018-01-10 17:50:59 +08004752static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304753{
4754 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004755 uint64_t written_frames = 0;
4756 uint64_t kernel_frames = 0;
4757 uint64_t dsp_frames = 0;
4758 uint64_t signed_frames = 0;
4759 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304760
4761 /* This adjustment accounts for buffering after app processor.
4762 * It is based on estimated DSP latency per use case, rather than exact.
4763 */
George Gao9ba8a142020-07-23 14:30:03 -07004764 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004765 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304766
Zhou Song48453a02018-01-10 17:50:59 +08004767 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004768 written_frames = out->written /
4769 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4770
Ashish Jain5106d362016-05-11 19:23:33 +05304771 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4772 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4773 * hence only estimate.
4774 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004775 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4776 kernel_frames = kernel_buffer_size /
4777 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304778
Weiyin Jiang4813da12020-05-28 00:37:28 +08004779 if (written_frames >= (kernel_frames + dsp_frames))
4780 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304781
Zhou Song48453a02018-01-10 17:50:59 +08004782 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304783 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004784 if (timestamp != NULL )
4785 *timestamp = out->writeAt;
4786 } else if (timestamp != NULL) {
4787 clock_gettime(CLOCK_MONOTONIC, timestamp);
4788 }
4789 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304790
Weiyin Jiang4813da12020-05-28 00:37:28 +08004791 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4792 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304793
4794 return actual_frames_rendered;
4795}
4796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4798{
4799 struct stream_out *out = (struct stream_out *)stream;
4800
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004801 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802}
4803
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004804static int out_set_sample_rate(struct audio_stream *stream __unused,
4805 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004806{
4807 return -ENOSYS;
4808}
4809
4810static size_t out_get_buffer_size(const struct audio_stream *stream)
4811{
4812 struct stream_out *out = (struct stream_out *)stream;
4813
Varun Balaraje49253e2017-07-06 19:48:56 +05304814 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304815 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304816 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304817 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4818 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4819 else
4820 return out->compr_config.fragment_size;
4821 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004822 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304823 else if (is_offload_usecase(out->usecase) &&
4824 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304825 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004826
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004827 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004828 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829}
4830
4831static uint32_t out_get_channels(const struct audio_stream *stream)
4832{
4833 struct stream_out *out = (struct stream_out *)stream;
4834
4835 return out->channel_mask;
4836}
4837
4838static audio_format_t out_get_format(const struct audio_stream *stream)
4839{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004840 struct stream_out *out = (struct stream_out *)stream;
4841
4842 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843}
4844
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004845static int out_set_format(struct audio_stream *stream __unused,
4846 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847{
4848 return -ENOSYS;
4849}
4850
4851static int out_standby(struct audio_stream *stream)
4852{
4853 struct stream_out *out = (struct stream_out *)stream;
4854 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004855 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004856
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304857 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4858 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004860 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004862 if (adev->adm_deregister_stream)
4863 adev->adm_deregister_stream(adev->adm_data, out->handle);
4864
Weiyin Jiang280ea742020-09-08 20:28:22 +08004865 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004866 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004867 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004868
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004869 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004871 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4872 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304873 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004874 pthread_mutex_unlock(&adev->lock);
4875 pthread_mutex_unlock(&out->lock);
4876 ALOGD("VOIP output entered standby");
4877 return 0;
4878 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004879 if (out->pcm) {
4880 pcm_close(out->pcm);
4881 out->pcm = NULL;
4882 }
Meng Wanga09da002020-04-20 12:56:04 +08004883 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4884 if (adev->haptic_pcm) {
4885 pcm_close(adev->haptic_pcm);
4886 adev->haptic_pcm = NULL;
4887 }
4888
4889 if (adev->haptic_buffer != NULL) {
4890 free(adev->haptic_buffer);
4891 adev->haptic_buffer = NULL;
4892 adev->haptic_buffer_size = 0;
4893 }
4894 adev->haptic_pcm_device_id = 0;
4895 }
4896
Haynes Mathew George16081042017-05-31 17:16:49 -07004897 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4898 do_stop = out->playback_started;
4899 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004900
4901 if (out->mmap_shared_memory_fd >= 0) {
4902 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4903 __func__, out->mmap_shared_memory_fd);
4904 close(out->mmap_shared_memory_fd);
4905 out->mmap_shared_memory_fd = -1;
4906 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004907 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004908 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004909 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304910 out->send_next_track_params = false;
4911 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004912 out->gapless_mdata.encoder_delay = 0;
4913 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004914 if (out->compr != NULL) {
4915 compress_close(out->compr);
4916 out->compr = NULL;
4917 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004918 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004919 if (do_stop) {
4920 stop_output_stream(out);
4921 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304922 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004923 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004924 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925 }
4926 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004927 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 return 0;
4929}
4930
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304931static int out_on_error(struct audio_stream *stream)
4932{
4933 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004934 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304935
4936 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004937 // always send CMD_ERROR for offload streams, this
4938 // is needed e.g. when SSR happens within compress_open
4939 // since the stream is active, offload_callback_thread is also active.
4940 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4941 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004942 }
4943 pthread_mutex_unlock(&out->lock);
4944
4945 status = out_standby(&out->stream.common);
4946
4947 lock_output_stream(out);
4948 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004949 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304950 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304951
4952 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4953 ALOGD("Setting previous card status if offline");
4954 out->prev_card_status_offline = true;
4955 }
4956
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304957 pthread_mutex_unlock(&out->lock);
4958
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004959 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304960}
4961
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304962/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004963 * standby implementation without locks, assumes that the callee already
4964 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304965 */
4966int out_standby_l(struct audio_stream *stream)
4967{
4968 struct stream_out *out = (struct stream_out *)stream;
4969 struct audio_device *adev = out->dev;
4970
4971 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4972 stream, out->usecase, use_case_table[out->usecase]);
4973
4974 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004975 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304976 if (adev->adm_deregister_stream)
4977 adev->adm_deregister_stream(adev->adm_data, out->handle);
4978
Weiyin Jiang280ea742020-09-08 20:28:22 +08004979 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304980 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004981 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304982
4983 out->standby = true;
4984 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4985 voice_extn_compress_voip_close_output_stream(stream);
4986 out->started = 0;
4987 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004988 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304989 return 0;
4990 } else if (!is_offload_usecase(out->usecase)) {
4991 if (out->pcm) {
4992 pcm_close(out->pcm);
4993 out->pcm = NULL;
4994 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004995 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4996 if (adev->haptic_pcm) {
4997 pcm_close(adev->haptic_pcm);
4998 adev->haptic_pcm = NULL;
4999 }
5000
5001 if (adev->haptic_buffer != NULL) {
5002 free(adev->haptic_buffer);
5003 adev->haptic_buffer = NULL;
5004 adev->haptic_buffer_size = 0;
5005 }
5006 adev->haptic_pcm_device_id = 0;
5007 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305008 } else {
5009 ALOGD("copl(%p):standby", out);
5010 out->send_next_track_params = false;
5011 out->is_compr_metadata_avail = false;
5012 out->gapless_mdata.encoder_delay = 0;
5013 out->gapless_mdata.encoder_padding = 0;
5014 if (out->compr != NULL) {
5015 compress_close(out->compr);
5016 out->compr = NULL;
5017 }
5018 }
5019 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005020 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305021 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005022 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305023 return 0;
5024}
5025
Aalique Grahame22e49102018-12-18 14:23:57 -08005026static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027{
Aalique Grahame22e49102018-12-18 14:23:57 -08005028 struct stream_out *out = (struct stream_out *)stream;
5029
5030 // We try to get the lock for consistency,
5031 // but it isn't necessary for these variables.
5032 // If we're not in standby, we may be blocked on a write.
5033 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5034 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5035 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305036#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005037 char buffer[256]; // for statistics formatting
5038 if (!is_offload_usecase(out->usecase)) {
5039 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5040 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5041 }
5042
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005043 if (out->start_latency_ms.n > 0) {
5044 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5045 dprintf(fd, " Start latency ms: %s\n", buffer);
5046 }
Dechen Chai22768452021-07-30 09:29:16 +05305047#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005048 if (locked) {
5049 pthread_mutex_unlock(&out->lock);
5050 }
5051
Dechen Chai22768452021-07-30 09:29:16 +05305052#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005053 // dump error info
5054 (void)error_log_dump(
5055 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305056#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057 return 0;
5058}
5059
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005060static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5061{
5062 int ret = 0;
5063 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005064
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005065 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005066 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005067 return -EINVAL;
5068 }
5069
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305070 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005071
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005072 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5073 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305074 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005075 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005076 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5077 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305078 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005079 }
5080
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005081 ALOGV("%s new encoder delay %u and padding %u", __func__,
5082 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5083
5084 return 0;
5085}
5086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005087static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5088{
5089 return out == adev->primary_output || out == adev->voice_tx_output;
5090}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005091
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305092// note: this call is safe only if the stream_cb is
5093// removed first in close_output_stream (as is done now).
5094static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5095{
5096 if (!stream || !parms)
5097 return;
5098
5099 struct stream_out *out = (struct stream_out *)stream;
5100 struct audio_device *adev = out->dev;
5101
5102 card_status_t status;
5103 int card;
5104 if (parse_snd_card_status(parms, &card, &status) < 0)
5105 return;
5106
5107 pthread_mutex_lock(&adev->lock);
5108 bool valid_cb = (card == adev->snd_card);
5109 pthread_mutex_unlock(&adev->lock);
5110
5111 if (!valid_cb)
5112 return;
5113
5114 lock_output_stream(out);
5115 if (out->card_status != status)
5116 out->card_status = status;
5117 pthread_mutex_unlock(&out->lock);
5118
5119 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5120 use_case_table[out->usecase],
5121 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5122
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305123 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305124 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305125 if (voice_is_call_state_active(adev) &&
5126 out == adev->primary_output) {
5127 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5128 pthread_mutex_lock(&adev->lock);
5129 voice_stop_call(adev);
5130 adev->mode = AUDIO_MODE_NORMAL;
5131 pthread_mutex_unlock(&adev->lock);
5132 }
5133 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305134 return;
5135}
5136
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005137int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005138 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005139{
5140 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005141 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005142 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005143 bool bypass_a2dp = false;
5144 bool reconfig = false;
5145 unsigned long service_interval = 0;
5146
5147 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005148 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5149
5150 list_init(&new_devices);
5151 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005152
5153 lock_output_stream(out);
5154 pthread_mutex_lock(&adev->lock);
5155
5156 /*
5157 * When HDMI cable is unplugged the music playback is paused and
5158 * the policy manager sends routing=0. But the audioflinger continues
5159 * to write data until standby time (3sec). As the HDMI core is
5160 * turned off, the write gets blocked.
5161 * Avoid this by routing audio to speaker until standby.
5162 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005163 if (is_single_device_type_equal(&out->device_list,
5164 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005165 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005166 !audio_extn_passthru_is_passthrough_stream(out) &&
5167 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005168 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005169 }
5170 /*
5171 * When A2DP is disconnected the
5172 * music playback is paused and the policy manager sends routing=0
5173 * But the audioflinger continues to write data until standby time
5174 * (3sec). As BT is turned off, the write gets blocked.
5175 * Avoid this by routing audio to speaker until standby.
5176 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005177 if (is_a2dp_out_device_type(&out->device_list) &&
5178 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005179 !audio_extn_a2dp_source_is_ready() &&
5180 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005181 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005182 }
5183 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005184 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005185 * and the policy manager send routing=0. But if the USB is connected
5186 * back before the standby time, AFE is not closed and opened
5187 * when USB is connected back. So routing to speker will guarantee
5188 * AFE reconfiguration and AFE will be opend once USB is connected again
5189 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005190 if (is_usb_out_device_type(&out->device_list) &&
5191 list_empty(&new_devices) &&
5192 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305193 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5194 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5195 else
5196 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005197 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005198 /* To avoid a2dp to sco overlapping / BT device improper state
5199 * check with BT lib about a2dp streaming support before routing
5200 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005201 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005202 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005203 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5204 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005205 //combo usecase just by pass a2dp
5206 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5207 bypass_a2dp = true;
5208 } else {
5209 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5210 /* update device to a2dp and don't route as BT returned error
5211 * However it is still possible a2dp routing called because
5212 * of current active device disconnection (like wired headset)
5213 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005214 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005215 pthread_mutex_unlock(&adev->lock);
5216 pthread_mutex_unlock(&out->lock);
5217 goto error;
5218 }
5219 }
5220 }
5221
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005222 // Workaround: If routing to an non existing usb device, fail gracefully
5223 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005224 if (is_usb_out_device_type(&new_devices)) {
5225 struct str_parms *parms =
5226 str_parms_create_str(get_usb_device_address(&new_devices));
5227 if (!parms)
5228 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005229 if (!audio_extn_usb_connected(NULL)) {
5230 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005231 pthread_mutex_unlock(&adev->lock);
5232 pthread_mutex_unlock(&out->lock);
5233 str_parms_destroy(parms);
5234 ret = -ENOSYS;
5235 goto error;
5236 }
5237 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005238 }
5239
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005240 // Workaround: If routing to an non existing hdmi device, fail gracefully
5241 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5242 (platform_get_edid_info_v2(adev->platform,
5243 out->extconn.cs.controller,
5244 out->extconn.cs.stream) != 0)) {
5245 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5246 pthread_mutex_unlock(&adev->lock);
5247 pthread_mutex_unlock(&out->lock);
5248 ret = -ENOSYS;
5249 goto error;
5250 }
5251
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005252 /*
5253 * select_devices() call below switches all the usecases on the same
5254 * backend to the new device. Refer to check_usecases_codec_backend() in
5255 * the select_devices(). But how do we undo this?
5256 *
5257 * For example, music playback is active on headset (deep-buffer usecase)
5258 * and if we go to ringtones and select a ringtone, low-latency usecase
5259 * will be started on headset+speaker. As we can't enable headset+speaker
5260 * and headset devices at the same time, select_devices() switches the music
5261 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5262 * So when the ringtone playback is completed, how do we undo the same?
5263 *
5264 * We are relying on the out_set_parameters() call on deep-buffer output,
5265 * once the ringtone playback is ended.
5266 * NOTE: We should not check if the current devices are same as new devices.
5267 * Because select_devices() must be called to switch back the music
5268 * playback to headset.
5269 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005270 if (!list_empty(&new_devices)) {
5271 bool same_dev = compare_devices(&out->device_list, &new_devices);
5272 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005273
5274 if (output_drives_call(adev, out)) {
5275 if (!voice_is_call_state_active(adev)) {
5276 if (adev->mode == AUDIO_MODE_IN_CALL) {
5277 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005278 ret = voice_start_call(adev);
5279 }
5280 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005281 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005282 adev->current_call_output = out;
5283 voice_update_devices_for_all_voice_usecases(adev);
5284 }
5285 }
5286
Mingshu Pang971ff702020-09-09 15:28:22 +08005287 if (is_usb_out_device_type(&out->device_list)) {
5288 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5289 audio_extn_usb_set_service_interval(true /*playback*/,
5290 service_interval,
5291 &reconfig);
5292 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5293 }
5294
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005295 if (!out->standby) {
5296 if (!same_dev) {
5297 ALOGV("update routing change");
5298 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5299 adev->perf_lock_opts,
5300 adev->perf_lock_opts_size);
5301 if (adev->adm_on_routing_change)
5302 adev->adm_on_routing_change(adev->adm_data,
5303 out->handle);
5304 }
5305 if (!bypass_a2dp) {
5306 select_devices(adev, out->usecase);
5307 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005308 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5309 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005310 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005311 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005312 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005313 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005314 }
5315
5316 if (!same_dev) {
5317 // on device switch force swap, lower functions will make sure
5318 // to check if swap is allowed or not.
5319 platform_set_swap_channels(adev, true);
5320 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5321 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005322 pthread_mutex_lock(&out->latch_lock);
5323 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5324 if (out->a2dp_muted) {
5325 out->a2dp_muted = false;
5326 if (is_offload_usecase(out->usecase))
5327 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5328 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5329 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005330 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005331 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005332 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5333 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5334 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005335 }
5336 }
5337
5338 pthread_mutex_unlock(&adev->lock);
5339 pthread_mutex_unlock(&out->lock);
5340
5341 /*handles device and call state changes*/
5342 audio_extn_extspk_update(adev->extspk);
5343
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005344 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005345error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005346 ALOGV("%s: exit: code(%d)", __func__, ret);
5347 return ret;
5348}
5349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005350static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5351{
5352 struct stream_out *out = (struct stream_out *)stream;
5353 struct audio_device *adev = out->dev;
5354 struct str_parms *parms;
5355 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005356 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005357 int ext_controller = -1;
5358 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005359
sangwoobc677242013-08-08 16:53:43 +09005360 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005361 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005362 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305363 if (!parms)
5364 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005365
5366 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5367 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005368 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005369 out->extconn.cs.controller = ext_controller;
5370 out->extconn.cs.stream = ext_stream;
5371 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5372 use_case_table[out->usecase], out->extconn.cs.controller,
5373 out->extconn.cs.stream);
5374 }
5375
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005376 if (out == adev->primary_output) {
5377 pthread_mutex_lock(&adev->lock);
5378 audio_extn_set_parameters(adev, parms);
5379 pthread_mutex_unlock(&adev->lock);
5380 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005381 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005382 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005383 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005384
5385 audio_extn_dts_create_state_notifier_node(out->usecase);
5386 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5387 popcount(out->channel_mask),
5388 out->playback_started);
5389
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005390 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005391 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005392
Surendar Karkaf51b5842018-04-26 11:28:38 +05305393 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5394 sizeof(value));
5395 if (err >= 0) {
5396 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5397 audio_extn_send_dual_mono_mixing_coefficients(out);
5398 }
5399
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305400 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5401 if (err >= 0) {
5402 strlcpy(out->profile, value, sizeof(out->profile));
5403 ALOGV("updating stream profile with value '%s'", out->profile);
5404 lock_output_stream(out);
5405 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5406 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005407 &out->device_list, out->flags,
5408 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305409 out->sample_rate, out->bit_width,
5410 out->channel_mask, out->profile,
5411 &out->app_type_cfg);
5412 pthread_mutex_unlock(&out->lock);
5413 }
5414
Alexy Joseph98988832017-01-13 14:56:59 -08005415 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005416 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5417 // and vendor.audio.hal.output.suspend.supported is set to true
5418 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005419 //check suspend parameter only for low latency and if the property
5420 //is enabled
5421 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5422 ALOGI("%s: got suspend_playback %s", __func__, value);
5423 lock_output_stream(out);
5424 if (!strncmp(value, "false", 5)) {
5425 //suspend_playback=false is supposed to set QOS value back to 75%
5426 //the mixer control sent with value Enable will achieve that
5427 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5428 } else if (!strncmp (value, "true", 4)) {
5429 //suspend_playback=true is supposed to remove QOS value
5430 //resetting the mixer control will set the default value
5431 //for the mixer control which is Disable and this removes the QOS vote
5432 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5433 } else {
5434 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5435 " got %s", __func__, value);
5436 ret = -1;
5437 }
5438
5439 if (ret != 0) {
5440 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5441 __func__, out->pm_qos_mixer_path, ret);
5442 }
5443
5444 pthread_mutex_unlock(&out->lock);
5445 }
5446 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005447
Alexy Joseph98988832017-01-13 14:56:59 -08005448 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305450error:
Eric Laurent994a6932013-07-17 11:51:42 -07005451 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005452 return ret;
5453}
5454
Paul McLeana50b7332018-12-17 08:24:21 -07005455static int in_set_microphone_direction(const struct audio_stream_in *stream,
5456 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005457 struct stream_in *in = (struct stream_in *)stream;
5458
5459 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5460
5461 in->direction = dir;
5462
5463 if (in->standby)
5464 return 0;
5465
5466 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005467}
5468
5469static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005470 struct stream_in *in = (struct stream_in *)stream;
5471
5472 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5473
5474 if (zoom > 1.0 || zoom < -1.0)
5475 return -EINVAL;
5476
5477 in->zoom = zoom;
5478
5479 if (in->standby)
5480 return 0;
5481
5482 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005483}
5484
5485
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005486static bool stream_get_parameter_channels(struct str_parms *query,
5487 struct str_parms *reply,
5488 audio_channel_mask_t *supported_channel_masks) {
5489 int ret = -1;
5490 char value[512];
5491 bool first = true;
5492 size_t i, j;
5493
5494 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5495 ret = 0;
5496 value[0] = '\0';
5497 i = 0;
5498 while (supported_channel_masks[i] != 0) {
5499 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5500 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5501 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305502 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005503
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305504 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005505 first = false;
5506 break;
5507 }
5508 }
5509 i++;
5510 }
5511 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5512 }
5513 return ret == 0;
5514}
5515
5516static bool stream_get_parameter_formats(struct str_parms *query,
5517 struct str_parms *reply,
5518 audio_format_t *supported_formats) {
5519 int ret = -1;
5520 char value[256];
5521 size_t i, j;
5522 bool first = true;
5523
5524 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5525 ret = 0;
5526 value[0] = '\0';
5527 i = 0;
5528 while (supported_formats[i] != 0) {
5529 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5530 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5531 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305532 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005533 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305534 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005535 first = false;
5536 break;
5537 }
5538 }
5539 i++;
5540 }
5541 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5542 }
5543 return ret == 0;
5544}
5545
5546static bool stream_get_parameter_rates(struct str_parms *query,
5547 struct str_parms *reply,
5548 uint32_t *supported_sample_rates) {
5549
5550 int i;
5551 char value[256];
5552 int ret = -1;
5553 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5554 ret = 0;
5555 value[0] = '\0';
5556 i=0;
5557 int cursor = 0;
5558 while (supported_sample_rates[i]) {
5559 int avail = sizeof(value) - cursor;
5560 ret = snprintf(value + cursor, avail, "%s%d",
5561 cursor > 0 ? "|" : "",
5562 supported_sample_rates[i]);
5563 if (ret < 0 || ret >= avail) {
5564 // if cursor is at the last element of the array
5565 // overwrite with \0 is duplicate work as
5566 // snprintf already put a \0 in place.
5567 // else
5568 // we had space to write the '|' at value[cursor]
5569 // (which will be overwritten) or no space to fill
5570 // the first element (=> cursor == 0)
5571 value[cursor] = '\0';
5572 break;
5573 }
5574 cursor += ret;
5575 ++i;
5576 }
5577 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5578 value);
5579 }
5580 return ret >= 0;
5581}
5582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005583static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5584{
5585 struct stream_out *out = (struct stream_out *)stream;
5586 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005587 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005588 char value[256];
5589 struct str_parms *reply = str_parms_create();
5590 size_t i, j;
5591 int ret;
5592 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005593
5594 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005595 if (reply) {
5596 str_parms_destroy(reply);
5597 }
5598 if (query) {
5599 str_parms_destroy(query);
5600 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005601 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5602 return NULL;
5603 }
5604
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005605 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005606 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5607 if (ret >= 0) {
5608 value[0] = '\0';
5609 i = 0;
5610 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005611 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5612 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005614 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005615 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005616 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005617 first = false;
5618 break;
5619 }
5620 }
5621 i++;
5622 }
5623 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5624 str = str_parms_to_str(reply);
5625 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005626 voice_extn_out_get_parameters(out, query, reply);
5627 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005628 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005629
Alexy Joseph62142aa2015-11-16 15:10:34 -08005630
5631 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5632 if (ret >= 0) {
5633 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305634 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5635 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005636 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305637 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005638 } else {
5639 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305640 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005641 }
5642 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005643 if (str)
5644 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005645 str = str_parms_to_str(reply);
5646 }
5647
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005648 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5649 if (ret >= 0) {
5650 value[0] = '\0';
5651 i = 0;
5652 first = true;
5653 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005654 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5655 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005656 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005657 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005658 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005659 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005660 first = false;
5661 break;
5662 }
5663 }
5664 i++;
5665 }
5666 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005667 if (str)
5668 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005669 str = str_parms_to_str(reply);
5670 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005671
5672 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5673 if (ret >= 0) {
5674 value[0] = '\0';
5675 i = 0;
5676 first = true;
5677 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005678 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5679 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005680 if (!first) {
5681 strlcat(value, "|", sizeof(value));
5682 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005683 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005684 first = false;
5685 break;
5686 }
5687 }
5688 i++;
5689 }
5690 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5691 if (str)
5692 free(str);
5693 str = str_parms_to_str(reply);
5694 }
5695
Alexy Joseph98988832017-01-13 14:56:59 -08005696 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5697 //only low latency track supports suspend_resume
5698 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005699 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005700 if (str)
5701 free(str);
5702 str = str_parms_to_str(reply);
5703 }
5704
5705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005706 str_parms_destroy(query);
5707 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005708 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709 return str;
5710}
5711
5712static uint32_t out_get_latency(const struct audio_stream_out *stream)
5713{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005714 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005716 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005717
Alexy Josephaa54c872014-12-03 02:46:47 -08005718 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305719 lock_output_stream(out);
5720 latency = audio_extn_utils_compress_get_dsp_latency(out);
5721 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005722 } else if ((out->realtime) ||
5723 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005724 // since the buffer won't be filled up faster than realtime,
5725 // return a smaller number
5726 if (out->config.rate)
5727 period_ms = (out->af_period_multiplier * out->config.period_size *
5728 1000) / (out->config.rate);
5729 else
5730 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005731 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005732 } else {
5733 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005734 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305735 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5736 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005737 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005738 }
5739
Zhou Songd2537a02020-06-11 22:04:46 +08005740 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005741 latency += audio_extn_a2dp_get_encoder_latency();
5742
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305743 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005744 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005745}
5746
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305747static float AmpToDb(float amplification)
5748{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305749 float db = DSD_VOLUME_MIN_DB;
5750 if (amplification > 0) {
5751 db = 20 * log10(amplification);
5752 if(db < DSD_VOLUME_MIN_DB)
5753 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305754 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305755 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305756}
5757
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305758#ifdef SOFT_VOLUME
5759static int out_set_soft_volume_params(struct audio_stream_out *stream)
5760{
5761 struct stream_out *out = (struct stream_out *)stream;
5762 int ret = 0;
5763 char mixer_ctl_name[128];
5764 struct audio_device *adev = out->dev;
5765 struct mixer_ctl *ctl = NULL;
5766 struct soft_step_volume_params *volume_params = NULL;
5767
5768 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5769 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5770 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5771 if (!ctl) {
5772 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5773 return -EINVAL;
5774 }
5775
5776 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5777 if (volume_params == NULL){
5778 ALOGE("%s : malloc is failed for volume params", __func__);
5779 return -EINVAL;
5780 } else {
5781 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5782 if (ret < 0) {
5783 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305784 ret = -EINVAL;
5785 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305786 }
5787
5788 }
5789 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5790 if (ret < 0) {
5791 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305792 ret = -EINVAL;
5793 goto ERR_EXIT;
5794 }
5795
5796 if (volume_params) {
5797 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305798 }
5799 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305800
5801ERR_EXIT:
5802 if (volume_params) {
5803 free(volume_params);
5804 }
5805 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305806}
5807#endif
5808
Arun Mirpuri5d170872019-03-26 13:21:31 -07005809static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5810 float right)
5811{
5812 struct stream_out *out = (struct stream_out *)stream;
5813 long volume = 0;
5814 char mixer_ctl_name[128] = "";
5815 struct audio_device *adev = out->dev;
5816 struct mixer_ctl *ctl = NULL;
5817 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5818 PCM_PLAYBACK);
5819
5820 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5821 "Playback %d Volume", pcm_device_id);
5822 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5823 if (!ctl) {
5824 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5825 __func__, mixer_ctl_name);
5826 return -EINVAL;
5827 }
5828 if (left != right)
5829 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5830 __func__, left, right);
5831 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5832 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5833 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5834 __func__, mixer_ctl_name, volume);
5835 return -EINVAL;
5836 }
5837 return 0;
5838}
5839
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305840static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5841 float right)
5842{
5843 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305844 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305845 char mixer_ctl_name[128];
5846 struct audio_device *adev = out->dev;
5847 struct mixer_ctl *ctl;
5848 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5849 PCM_PLAYBACK);
5850
5851 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5852 "Compress Playback %d Volume", pcm_device_id);
5853 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5854 if (!ctl) {
5855 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5856 __func__, mixer_ctl_name);
5857 return -EINVAL;
5858 }
5859 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5860 __func__, mixer_ctl_name, left, right);
5861 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5862 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5863 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5864
5865 return 0;
5866}
5867
Zhou Song2b8f28f2017-09-11 10:51:38 +08005868static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5869 float right)
5870{
5871 struct stream_out *out = (struct stream_out *)stream;
5872 char mixer_ctl_name[] = "App Type Gain";
5873 struct audio_device *adev = out->dev;
5874 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305875 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005876
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005877 if (!is_valid_volume(left, right)) {
5878 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5879 __func__, left, right);
5880 return -EINVAL;
5881 }
5882
Zhou Song2b8f28f2017-09-11 10:51:38 +08005883 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5884 if (!ctl) {
5885 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5886 __func__, mixer_ctl_name);
5887 return -EINVAL;
5888 }
5889
5890 set_values[0] = 0; //0: Rx Session 1:Tx Session
5891 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305892 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5893 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005894
5895 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5896 return 0;
5897}
5898
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305899static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5900 float right)
5901{
5902 struct stream_out *out = (struct stream_out *)stream;
5903 /* Volume control for pcm playback */
5904 if (left != right) {
5905 return -EINVAL;
5906 } else {
5907 char mixer_ctl_name[128];
5908 struct audio_device *adev = out->dev;
5909 struct mixer_ctl *ctl;
5910 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5911 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5912 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5913 if (!ctl) {
5914 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5915 return -EINVAL;
5916 }
5917
5918 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5919 int ret = mixer_ctl_set_value(ctl, 0, volume);
5920 if (ret < 0) {
5921 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5922 return -EINVAL;
5923 }
5924
5925 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5926
5927 return 0;
5928 }
5929}
5930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005931static int out_set_volume(struct audio_stream_out *stream, float left,
5932 float right)
5933{
Eric Laurenta9024de2013-04-04 09:19:12 -07005934 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005935 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305936 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005937
Arun Mirpuri5d170872019-03-26 13:21:31 -07005938 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005939 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5940 /* only take left channel into account: the API is for stereo anyway */
5941 out->muted = (left == 0.0f);
5942 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005943 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305944 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005945 /*
5946 * Set mute or umute on HDMI passthrough stream.
5947 * Only take left channel into account.
5948 * Mute is 0 and unmute 1
5949 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305950 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305951 } else if (out->format == AUDIO_FORMAT_DSD){
5952 char mixer_ctl_name[128] = "DSD Volume";
5953 struct audio_device *adev = out->dev;
5954 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5955
5956 if (!ctl) {
5957 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5958 __func__, mixer_ctl_name);
5959 return -EINVAL;
5960 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305961 volume[0] = (long)(AmpToDb(left));
5962 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305963 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5964 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005965 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005966 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005967 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5968 struct listnode *node = NULL;
5969 list_for_each(node, &adev->active_outputs_list) {
5970 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5971 streams_output_ctxt_t,
5972 list);
5973 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5974 out->volume_l = out_ctxt->output->volume_l;
5975 out->volume_r = out_ctxt->output->volume_r;
5976 }
5977 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005978 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005979 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005980 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5981 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005982 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005983 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005984 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005985 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005986 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5987 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305988 ret = out_set_compr_volume(stream, left, right);
5989 out->volume_l = left;
5990 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005991 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305992 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005993 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005994 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005995 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5996 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005997 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005998 if (!out->standby) {
5999 audio_extn_utils_send_app_type_gain(out->dev,
6000 out->app_type_cfg.app_type,
6001 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006002 if (!out->a2dp_muted)
6003 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006004 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006005 out->volume_l = left;
6006 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006007 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006008 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006009 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6010 ALOGV("%s: MMAP set volume called", __func__);
6011 if (!out->standby)
6012 ret = out_set_mmap_volume(stream, left, right);
6013 out->volume_l = left;
6014 out->volume_r = right;
6015 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306016 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306017 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6018 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006019 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306020 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006021 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306022 ret = out_set_pcm_volume(stream, left, right);
6023 else
6024 out->apply_volume = true;
6025
6026 out->volume_l = left;
6027 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006028 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306029 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006030 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6031 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006032 pthread_mutex_lock(&out->latch_lock);
6033 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006034 ret = out_set_pcm_volume(stream, left, right);
6035 out->volume_l = left;
6036 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006037 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006038 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006039 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006041 return -ENOSYS;
6042}
6043
Zhou Songc9672822017-08-16 16:01:39 +08006044static void update_frames_written(struct stream_out *out, size_t bytes)
6045{
6046 size_t bpf = 0;
6047
6048 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6049 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6050 bpf = 1;
6051 else if (!is_offload_usecase(out->usecase))
6052 bpf = audio_bytes_per_sample(out->format) *
6053 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006054
6055 pthread_mutex_lock(&out->position_query_lock);
6056 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006057 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006058 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6059 }
6060 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006061}
6062
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006063int split_and_write_audio_haptic_data(struct stream_out *out,
6064 const void *buffer, size_t bytes_to_write)
6065{
6066 struct audio_device *adev = out->dev;
6067
6068 int ret = 0;
6069 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6070 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6071 size_t frame_size = channel_count * bytes_per_sample;
6072 size_t frame_count = bytes_to_write / frame_size;
6073
6074 bool force_haptic_path =
6075 property_get_bool("vendor.audio.test_haptic", false);
6076
6077 // extract Haptics data from Audio buffer
6078 bool alloc_haptic_buffer = false;
6079 int haptic_channel_count = adev->haptics_config.channels;
6080 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6081 size_t audio_frame_size = frame_size - haptic_frame_size;
6082 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6083
6084 if (adev->haptic_buffer == NULL) {
6085 alloc_haptic_buffer = true;
6086 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6087 free(adev->haptic_buffer);
6088 adev->haptic_buffer_size = 0;
6089 alloc_haptic_buffer = true;
6090 }
6091
6092 if (alloc_haptic_buffer) {
6093 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006094 if(adev->haptic_buffer == NULL) {
6095 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6096 return -ENOMEM;
6097 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006098 adev->haptic_buffer_size = total_haptic_buffer_size;
6099 }
6100
6101 size_t src_index = 0, aud_index = 0, hap_index = 0;
6102 uint8_t *audio_buffer = (uint8_t *)buffer;
6103 uint8_t *haptic_buffer = adev->haptic_buffer;
6104
6105 // This is required for testing only. This works for stereo data only.
6106 // One channel is fed to audio stream and other to haptic stream for testing.
6107 if (force_haptic_path)
6108 audio_frame_size = haptic_frame_size = bytes_per_sample;
6109
6110 for (size_t i = 0; i < frame_count; i++) {
6111 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6112 audio_frame_size);
6113 aud_index += audio_frame_size;
6114 src_index += audio_frame_size;
6115
6116 if (adev->haptic_pcm)
6117 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6118 haptic_frame_size);
6119 hap_index += haptic_frame_size;
6120 src_index += haptic_frame_size;
6121
6122 // This is required for testing only.
6123 // Discard haptic channel data.
6124 if (force_haptic_path)
6125 src_index += haptic_frame_size;
6126 }
6127
6128 // write to audio pipeline
6129 ret = pcm_write(out->pcm, (void *)audio_buffer,
6130 frame_count * audio_frame_size);
6131
6132 // write to haptics pipeline
6133 if (adev->haptic_pcm)
6134 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6135 frame_count * haptic_frame_size);
6136
6137 return ret;
6138}
6139
Aalique Grahame22e49102018-12-18 14:23:57 -08006140#ifdef NO_AUDIO_OUT
6141static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6142 const void *buffer __unused, size_t bytes)
6143{
6144 struct stream_out *out = (struct stream_out *)stream;
6145
6146 /* No Output device supported other than BT for playback.
6147 * Sleep for the amount of buffer duration
6148 */
6149 lock_output_stream(out);
6150 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6151 (const struct audio_stream_out *)&out->stream) /
6152 out_get_sample_rate(&out->stream.common));
6153 pthread_mutex_unlock(&out->lock);
6154 return bytes;
6155}
6156#endif
6157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006158static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6159 size_t bytes)
6160{
6161 struct stream_out *out = (struct stream_out *)stream;
6162 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006163 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306164 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006165 const size_t frame_size = audio_stream_out_frame_size(stream);
6166 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306167 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006168 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006169
Haynes Mathew George380745d2017-10-04 15:27:45 -07006170 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006171 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306172
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006173 if (CARD_STATUS_OFFLINE == out->card_status ||
6174 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006175
Dhananjay Kumarac341582017-02-23 23:42:25 +05306176 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306177 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306178 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6179 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006180 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306181 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306182 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306183 ALOGD(" %s: sound card is not active/SSR state", __func__);
6184 ret= -EIO;
6185 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306186 }
6187 }
6188
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306189 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306190 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306191 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306192 goto exit;
6193 }
6194
Haynes Mathew George16081042017-05-31 17:16:49 -07006195 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6196 ret = -EINVAL;
6197 goto exit;
6198 }
6199
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006200 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306201 !out->is_iec61937_info_available) {
6202
6203 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6204 out->is_iec61937_info_available = true;
6205 } else if (audio_extn_passthru_is_enabled()) {
6206 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306207 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306208
6209 if((out->format == AUDIO_FORMAT_DTS) ||
6210 (out->format == AUDIO_FORMAT_DTS_HD)) {
6211 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6212 buffer, bytes);
6213 if (ret) {
6214 if (ret != -ENOSYS) {
6215 out->is_iec61937_info_available = false;
6216 ALOGD("iec61937 transmission info not yet updated retry");
6217 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306218 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306219 /* if stream has started and after that there is
6220 * stream config change (iec transmission config)
6221 * then trigger select_device to update backend configuration.
6222 */
6223 out->stream_config_changed = true;
6224 pthread_mutex_lock(&adev->lock);
6225 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306226 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006227 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306228 ret = -EINVAL;
6229 goto exit;
6230 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306231 pthread_mutex_unlock(&adev->lock);
6232 out->stream_config_changed = false;
6233 out->is_iec61937_info_available = true;
6234 }
6235 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306236
Meng Wang4c32fb42020-01-16 17:57:11 +08006237#ifdef AUDIO_GKI_ENABLED
6238 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6239 compr_passthr = out->compr_config.codec->reserved[0];
6240#else
6241 compr_passthr = out->compr_config.codec->compr_passthr;
6242#endif
6243
Garmond Leung317cbf12017-09-13 16:20:50 -07006244 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006245 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306246 (out->is_iec61937_info_available == true)) {
6247 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6248 ret = -EINVAL;
6249 goto exit;
6250 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306251 }
6252 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306253
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006254 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006255 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006256 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6257 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006258 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306259 ret = -EIO;
6260 goto exit;
6261 }
6262 }
6263 }
6264
Weiyin Jiangabedea32020-12-09 12:49:19 +08006265 if (is_usb_out_device_type(&out->device_list) &&
6266 !audio_extn_usb_connected(NULL)) {
6267 ret = -EIO;
6268 goto exit;
6269 }
6270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006271 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006272 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006273 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6274
Eric Laurent150dbfe2013-02-27 14:31:02 -08006275 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006276 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6277 ret = voice_extn_compress_voip_start_output_stream(out);
6278 else
6279 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006280 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006281 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006282 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006283 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006284 goto exit;
6285 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306286 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006287 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006288
6289 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006290 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006291 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306292 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006293 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006294 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306295
6296 if ((out->is_iec61937_info_available == true) &&
6297 (audio_extn_passthru_is_passthrough_stream(out))&&
6298 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6299 ret = -EINVAL;
6300 goto exit;
6301 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306302 if (out->set_dual_mono)
6303 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006304
Dechen Chai22768452021-07-30 09:29:16 +05306305#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006306 // log startup time in ms.
6307 simple_stats_log(
6308 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306309#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006310 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006311
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006312 if (adev->is_channel_status_set == false &&
6313 compare_device_type(&out->device_list,
6314 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006315 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306316 adev->is_channel_status_set = true;
6317 }
6318
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306319 if ((adev->use_old_pspd_mix_ctrl == true) &&
6320 (out->pspd_coeff_sent == false)) {
6321 /*
6322 * Need to resend pspd coefficients after stream started for
6323 * older kernel version as it does not save the coefficients
6324 * and also stream has to be started for coeff to apply.
6325 */
6326 usecase = get_usecase_from_list(adev, out->usecase);
6327 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306328 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306329 out->pspd_coeff_sent = true;
6330 }
6331 }
6332
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006333 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006334 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006335 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006336 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006337 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6338 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306339 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6340 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006341 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306342 out->send_next_track_params = false;
6343 out->is_compr_metadata_avail = false;
6344 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006345 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306346 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306347 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006348
Ashish Jain83a6cc22016-06-28 14:34:17 +05306349 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306350 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306351 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306352 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006353 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306354 return -EINVAL;
6355 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306356 audio_format_t dst_format = out->hal_op_format;
6357 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306358
Dieter Luecking5d57def2018-09-07 14:23:37 +02006359 /* prevent division-by-zero */
6360 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6361 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6362 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6363 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306364 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006365 ATRACE_END();
6366 return -EINVAL;
6367 }
6368
Ashish Jainf1eaa582016-05-23 20:54:24 +05306369 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6370 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6371
Ashish Jain83a6cc22016-06-28 14:34:17 +05306372 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306373 dst_format,
6374 buffer,
6375 src_format,
6376 frames);
6377
Ashish Jain83a6cc22016-06-28 14:34:17 +05306378 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306379 bytes_to_write);
6380
6381 /*Convert written bytes in audio flinger format*/
6382 if (ret > 0)
6383 ret = ((ret * format_to_bitwidth_table[out->format]) /
6384 format_to_bitwidth_table[dst_format]);
6385 }
6386 } else
6387 ret = compress_write(out->compr, buffer, bytes);
6388
Zhou Songc9672822017-08-16 16:01:39 +08006389 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6390 update_frames_written(out, bytes);
6391
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306392 if (ret < 0)
6393 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006394 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306395 /*msg to cb thread only if non blocking write is enabled*/
6396 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306397 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006398 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306399 } else if (-ENETRESET == ret) {
6400 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306401 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306402 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306403 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006404 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306405 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006406 }
Ashish Jain5106d362016-05-11 19:23:33 +05306407
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306408 /* Call compr start only when non-zero bytes of data is there to be rendered */
6409 if (!out->playback_started && ret > 0) {
6410 int status = compress_start(out->compr);
6411 if (status < 0) {
6412 ret = status;
6413 ALOGE("%s: compr start failed with err %d", __func__, errno);
6414 goto exit;
6415 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006416 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006417 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006418 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006419 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006420 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006421
6422 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6423 popcount(out->channel_mask),
6424 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006425 }
6426 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006427 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006428 return ret;
6429 } else {
6430 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006431 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006432 if (out->muted)
6433 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006434 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6435 __func__, frames, frame_size, bytes_to_write);
6436
Aalique Grahame22e49102018-12-18 14:23:57 -08006437 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006438 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6439 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6440 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006441 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6442 int16_t *src = (int16_t *)buffer;
6443 int16_t *dst = (int16_t *)buffer;
6444
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006445 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006446 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006447 "out_write called for %s use case with wrong properties",
6448 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006449
6450 /*
6451 * FIXME: this can be removed once audio flinger mixer supports
6452 * mono output
6453 */
6454
6455 /*
6456 * Code below goes over each frame in the buffer and adds both
6457 * L and R samples and then divides by 2 to convert to mono
6458 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006459 if (channel_count == 2) {
6460 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6461 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6462 }
6463 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006464 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006465 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006466
6467 // Note: since out_get_presentation_position() is called alternating with out_write()
6468 // by AudioFlinger, we can check underruns using the prior timestamp read.
6469 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6470 if (out->last_fifo_valid) {
6471 // compute drain to see if there is an underrun.
6472 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306473 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6474 int64_t frames_by_time =
6475 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6476 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006477 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6478
6479 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306480#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006481 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306482#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006483
6484 ALOGW("%s: underrun(%lld) "
6485 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6486 __func__,
6487 (long long)out->fifo_underruns.n,
6488 (long long)frames_by_time,
6489 (long long)out->last_fifo_frames_remaining);
6490 }
6491 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6492 }
6493
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306494 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006495
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006496 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006497
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006498 if (out->config.rate)
6499 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6500 out->config.rate;
6501
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006502 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006503 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6504
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006505 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006506 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006507 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306508 out->convert_buffer != NULL) {
6509
6510 memcpy_by_audio_format(out->convert_buffer,
6511 out->hal_op_format,
6512 buffer,
6513 out->hal_ip_format,
6514 out->config.period_size * out->config.channels);
6515
6516 ret = pcm_write(out->pcm, out->convert_buffer,
6517 (out->config.period_size *
6518 out->config.channels *
6519 format_to_bitwidth_table[out->hal_op_format]));
6520 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306521 /*
6522 * To avoid underrun in DSP when the application is not pumping
6523 * data at required rate, check for the no. of bytes and ignore
6524 * pcm_write if it is less than actual buffer size.
6525 * It is a work around to a change in compress VOIP driver.
6526 */
6527 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6528 bytes < (out->config.period_size * out->config.channels *
6529 audio_bytes_per_sample(out->format))) {
6530 size_t voip_buf_size =
6531 out->config.period_size * out->config.channels *
6532 audio_bytes_per_sample(out->format);
6533 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6534 __func__, bytes, voip_buf_size);
6535 usleep(((uint64_t)voip_buf_size - bytes) *
6536 1000000 / audio_stream_out_frame_size(stream) /
6537 out_get_sample_rate(&out->stream.common));
6538 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006539 } else {
6540 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6541 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6542 else
6543 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6544 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306545 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006546
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006547 release_out_focus(out);
6548
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306549 if (ret < 0)
6550 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006551 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306552 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006554 }
6555
6556exit:
Zhou Songc9672822017-08-16 16:01:39 +08006557 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306558 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306559 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006561 pthread_mutex_unlock(&out->lock);
6562
6563 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006564 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006565 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306566 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306567 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306568 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306569 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306570 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306571 out->standby = true;
6572 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306573 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006574 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6575 /* prevent division-by-zero */
6576 uint32_t stream_size = audio_stream_out_frame_size(stream);
6577 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006578
Dieter Luecking5d57def2018-09-07 14:23:37 +02006579 if ((stream_size == 0) || (srate == 0)) {
6580 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6581 ATRACE_END();
6582 return -EINVAL;
6583 }
6584 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6585 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006586 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306587 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006588 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006589 return ret;
6590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006592 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006593 return bytes;
6594}
6595
6596static int out_get_render_position(const struct audio_stream_out *stream,
6597 uint32_t *dsp_frames)
6598{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006599 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006600
6601 if (dsp_frames == NULL)
6602 return -EINVAL;
6603
6604 *dsp_frames = 0;
6605 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006606 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306607
6608 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6609 * this operation and adev_close_output_stream(where out gets reset).
6610 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306611 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006612 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306613 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006614 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306615 return 0;
6616 }
6617
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006618 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306619 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306620 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006621 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306622 if (ret < 0)
6623 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006624 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306625 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006626 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306627 if (-ENETRESET == ret) {
6628 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306629 out->card_status = CARD_STATUS_OFFLINE;
6630 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306631 } else if(ret < 0) {
6632 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306633 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006634 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6635 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306636 /*
6637 * Handle corner case where compress session is closed during SSR
6638 * and timestamp is queried
6639 */
6640 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306641 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306642 } else if (out->prev_card_status_offline) {
6643 ALOGE("ERROR: previously sound card was offline,return error");
6644 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306645 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306646 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006647 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306648 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306649 pthread_mutex_unlock(&out->lock);
6650 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006651 } else if (audio_is_linear_pcm(out->format)) {
6652 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006653 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006654 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006655 } else
6656 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006657}
6658
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006659static int out_add_audio_effect(const struct audio_stream *stream __unused,
6660 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006661{
6662 return 0;
6663}
6664
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006665static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6666 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006667{
6668 return 0;
6669}
6670
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006671static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6672 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006673{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306674 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006675}
6676
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006677static int out_get_presentation_position(const struct audio_stream_out *stream,
6678 uint64_t *frames, struct timespec *timestamp)
6679{
6680 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306681 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006682 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006683
Ashish Jain5106d362016-05-11 19:23:33 +05306684 /* below piece of code is not guarded against any lock because audioFliner serializes
6685 * this operation and adev_close_output_stream( where out gets reset).
6686 */
6687 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306688 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006689 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306690 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6691 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6692 return 0;
6693 }
6694
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006695 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006696
Ashish Jain5106d362016-05-11 19:23:33 +05306697 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6698 ret = compress_get_tstamp(out->compr, &dsp_frames,
6699 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006700 // Adjustment accounts for A2dp encoder latency with offload usecases
6701 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006702 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006703 unsigned long offset =
6704 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6705 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6706 }
Ashish Jain5106d362016-05-11 19:23:33 +05306707 ALOGVV("%s rendered frames %ld sample_rate %d",
6708 __func__, dsp_frames, out->sample_rate);
6709 *frames = dsp_frames;
6710 if (ret < 0)
6711 ret = -errno;
6712 if (-ENETRESET == ret) {
6713 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306714 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306715 ret = -EINVAL;
6716 } else
6717 ret = 0;
6718 /* this is the best we can do */
6719 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006720 } else {
6721 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006722 unsigned int avail;
6723 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006724 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006725 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006726
Andy Hunga1f48fa2019-07-01 18:14:53 -07006727 if (out->kernel_buffer_size > avail) {
6728 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6729 } else {
6730 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6731 __func__, avail, out->kernel_buffer_size);
6732 avail = out->kernel_buffer_size;
6733 frames_temp = out->last_fifo_frames_remaining = 0;
6734 }
6735 out->last_fifo_valid = true;
6736 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6737
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006738 if (out->written >= frames_temp)
6739 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006740
Andy Hunga1f48fa2019-07-01 18:14:53 -07006741 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6742 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6743
Weiyin Jiangd4633762018-03-16 12:05:03 +08006744 // This adjustment accounts for buffering after app processor.
6745 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006746 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006747 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006748 if (signed_frames >= frames_temp)
6749 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006750
Weiyin Jiangd4633762018-03-16 12:05:03 +08006751 // Adjustment accounts for A2dp encoder latency with non offload usecases
6752 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006753 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006754 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6755 if (signed_frames >= frames_temp)
6756 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006757 }
6758
6759 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006760 *frames = signed_frames;
6761 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006762 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006763 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006764 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006765 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006766 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306767 *frames = out->written;
6768 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306769 if (is_offload_usecase(out->usecase))
6770 ret = -EINVAL;
6771 else
6772 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006773 }
6774 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006775 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006776 return ret;
6777}
6778
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006779static int out_set_callback(struct audio_stream_out *stream,
6780 stream_callback_t callback, void *cookie)
6781{
6782 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006783 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006784
6785 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006786 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006787 out->client_callback = callback;
6788 out->client_cookie = cookie;
6789 if (out->adsp_hdlr_stream_handle) {
6790 ret = audio_extn_adsp_hdlr_stream_set_callback(
6791 out->adsp_hdlr_stream_handle,
6792 callback,
6793 cookie);
6794 if (ret)
6795 ALOGW("%s:adsp hdlr callback registration failed %d",
6796 __func__, ret);
6797 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006798 pthread_mutex_unlock(&out->lock);
6799 return 0;
6800}
6801
6802static int out_pause(struct audio_stream_out* stream)
6803{
6804 struct stream_out *out = (struct stream_out *)stream;
6805 int status = -ENOSYS;
6806 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006807 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006808 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306809 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006810 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006811 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006812 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306813 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306814 status = compress_pause(out->compr);
6815
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006816 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006817
Mingming Yin21854652016-04-13 11:54:02 -07006818 if (audio_extn_passthru_is_active()) {
6819 ALOGV("offload use case, pause passthru");
6820 audio_extn_passthru_on_pause(out);
6821 }
6822
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306823 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006824 audio_extn_dts_notify_playback_state(out->usecase, 0,
6825 out->sample_rate, popcount(out->channel_mask),
6826 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006827 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006828 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006829 pthread_mutex_unlock(&out->lock);
6830 }
6831 return status;
6832}
6833
6834static int out_resume(struct audio_stream_out* stream)
6835{
6836 struct stream_out *out = (struct stream_out *)stream;
6837 int status = -ENOSYS;
6838 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006839 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006840 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306841 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006842 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006843 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006844 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306845 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306846 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006847 }
6848 if (!status) {
6849 out->offload_state = OFFLOAD_STATE_PLAYING;
6850 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306851 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006852 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6853 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006854 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006855 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006856 pthread_mutex_unlock(&out->lock);
6857 }
6858 return status;
6859}
6860
6861static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6862{
6863 struct stream_out *out = (struct stream_out *)stream;
6864 int status = -ENOSYS;
6865 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006866 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006867 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006868 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6869 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6870 else
6871 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6872 pthread_mutex_unlock(&out->lock);
6873 }
6874 return status;
6875}
6876
6877static int out_flush(struct audio_stream_out* stream)
6878{
6879 struct stream_out *out = (struct stream_out *)stream;
6880 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006881 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006882 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006883 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006884 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006885 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306886 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006887 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006888 } else {
6889 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306890 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006891 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006892 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006893 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006894 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006895 return 0;
6896 }
6897 return -ENOSYS;
6898}
6899
Haynes Mathew George16081042017-05-31 17:16:49 -07006900static int out_stop(const struct audio_stream_out* stream)
6901{
6902 struct stream_out *out = (struct stream_out *)stream;
6903 struct audio_device *adev = out->dev;
6904 int ret = -ENOSYS;
6905
6906 ALOGV("%s", __func__);
6907 pthread_mutex_lock(&adev->lock);
6908 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6909 out->playback_started && out->pcm != NULL) {
6910 pcm_stop(out->pcm);
6911 ret = stop_output_stream(out);
6912 out->playback_started = false;
6913 }
6914 pthread_mutex_unlock(&adev->lock);
6915 return ret;
6916}
6917
6918static int out_start(const struct audio_stream_out* stream)
6919{
6920 struct stream_out *out = (struct stream_out *)stream;
6921 struct audio_device *adev = out->dev;
6922 int ret = -ENOSYS;
6923
6924 ALOGV("%s", __func__);
6925 pthread_mutex_lock(&adev->lock);
6926 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6927 !out->playback_started && out->pcm != NULL) {
6928 ret = start_output_stream(out);
6929 if (ret == 0) {
6930 out->playback_started = true;
6931 }
6932 }
6933 pthread_mutex_unlock(&adev->lock);
6934 return ret;
6935}
6936
6937/*
6938 * Modify config->period_count based on min_size_frames
6939 */
6940static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6941{
6942 int periodCountRequested = (min_size_frames + config->period_size - 1)
6943 / config->period_size;
6944 int periodCount = MMAP_PERIOD_COUNT_MIN;
6945
6946 ALOGV("%s original config.period_size = %d config.period_count = %d",
6947 __func__, config->period_size, config->period_count);
6948
6949 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6950 periodCount *= 2;
6951 }
6952 config->period_count = periodCount;
6953
6954 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6955}
6956
Phil Burkfe17efd2019-03-25 10:23:35 -07006957// Read offset for the positional timestamp from a persistent vendor property.
6958// This is to workaround apparent inaccuracies in the timing information that
6959// is used by the AAudio timing model. The inaccuracies can cause glitches.
6960static int64_t get_mmap_out_time_offset() {
6961 const int32_t kDefaultOffsetMicros = 0;
6962 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006963 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006964 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6965 return mmap_time_offset_micros * (int64_t)1000;
6966}
6967
Haynes Mathew George16081042017-05-31 17:16:49 -07006968static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6969 int32_t min_size_frames,
6970 struct audio_mmap_buffer_info *info)
6971{
6972 struct stream_out *out = (struct stream_out *)stream;
6973 struct audio_device *adev = out->dev;
6974 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006975 unsigned int offset1 = 0;
6976 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006977 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006978 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006979 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006980
Arun Mirpuri5d170872019-03-26 13:21:31 -07006981 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306982 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006983 pthread_mutex_lock(&adev->lock);
6984
Sharad Sanglec6f32552018-05-04 16:15:38 +05306985 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006986 CARD_STATUS_OFFLINE == adev->card_status ||
6987 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306988 ALOGW("out->card_status or adev->card_status offline, try again");
6989 ret = -EIO;
6990 goto exit;
6991 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306992 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006993 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6994 ret = -EINVAL;
6995 goto exit;
6996 }
6997 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6998 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6999 ret = -ENOSYS;
7000 goto exit;
7001 }
7002 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7003 if (out->pcm_device_id < 0) {
7004 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7005 __func__, out->pcm_device_id, out->usecase);
7006 ret = -EINVAL;
7007 goto exit;
7008 }
7009
7010 adjust_mmap_period_count(&out->config, min_size_frames);
7011
Arun Mirpuri5d170872019-03-26 13:21:31 -07007012 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007013 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7014 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7015 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307016 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307017 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7018 out->card_status = CARD_STATUS_OFFLINE;
7019 adev->card_status = CARD_STATUS_OFFLINE;
7020 ret = -EIO;
7021 goto exit;
7022 }
7023
Haynes Mathew George16081042017-05-31 17:16:49 -07007024 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7025 step = "open";
7026 ret = -ENODEV;
7027 goto exit;
7028 }
7029 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7030 if (ret < 0) {
7031 step = "begin";
7032 goto exit;
7033 }
juyuchen626833d2019-06-04 16:48:02 +08007034
7035 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007036 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007037 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007038 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007039 ret = platform_get_mmap_data_fd(adev->platform,
7040 out->pcm_device_id, 0 /*playback*/,
7041 &info->shared_memory_fd,
7042 &mmap_size);
7043 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007044 // Fall back to non exclusive mode
7045 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7046 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007047 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7048 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7049
Arun Mirpuri5d170872019-03-26 13:21:31 -07007050 if (mmap_size < buffer_size) {
7051 step = "mmap";
7052 goto exit;
7053 }
juyuchen626833d2019-06-04 16:48:02 +08007054 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007055 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007056 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007057 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007058
7059 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7060 if (ret < 0) {
7061 step = "commit";
7062 goto exit;
7063 }
7064
Phil Burkfe17efd2019-03-25 10:23:35 -07007065 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7066
Haynes Mathew George16081042017-05-31 17:16:49 -07007067 out->standby = false;
7068 ret = 0;
7069
Arun Mirpuri5d170872019-03-26 13:21:31 -07007070 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007071 __func__, info->shared_memory_address, info->buffer_size_frames);
7072
7073exit:
7074 if (ret != 0) {
7075 if (out->pcm == NULL) {
7076 ALOGE("%s: %s - %d", __func__, step, ret);
7077 } else {
7078 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7079 pcm_close(out->pcm);
7080 out->pcm = NULL;
7081 }
7082 }
7083 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307084 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007085 return ret;
7086}
7087
7088static int out_get_mmap_position(const struct audio_stream_out *stream,
7089 struct audio_mmap_position *position)
7090{
7091 struct stream_out *out = (struct stream_out *)stream;
7092 ALOGVV("%s", __func__);
7093 if (position == NULL) {
7094 return -EINVAL;
7095 }
7096 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007097 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007098 return -ENOSYS;
7099 }
7100 if (out->pcm == NULL) {
7101 return -ENOSYS;
7102 }
7103
7104 struct timespec ts = { 0, 0 };
7105 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7106 if (ret < 0) {
7107 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7108 return ret;
7109 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007110 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7111 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007112 return 0;
7113}
7114
7115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007116/** audio_stream_in implementation **/
7117static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7118{
7119 struct stream_in *in = (struct stream_in *)stream;
7120
7121 return in->config.rate;
7122}
7123
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007124static int in_set_sample_rate(struct audio_stream *stream __unused,
7125 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007126{
7127 return -ENOSYS;
7128}
7129
7130static size_t in_get_buffer_size(const struct audio_stream *stream)
7131{
7132 struct stream_in *in = (struct stream_in *)stream;
7133
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007134 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7135 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007136 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
7137 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307138 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307139 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007140
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007141 return in->config.period_size * in->af_period_multiplier *
7142 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007143}
7144
7145static uint32_t in_get_channels(const struct audio_stream *stream)
7146{
7147 struct stream_in *in = (struct stream_in *)stream;
7148
7149 return in->channel_mask;
7150}
7151
7152static audio_format_t in_get_format(const struct audio_stream *stream)
7153{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007154 struct stream_in *in = (struct stream_in *)stream;
7155
7156 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007157}
7158
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007159static int in_set_format(struct audio_stream *stream __unused,
7160 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161{
7162 return -ENOSYS;
7163}
7164
7165static int in_standby(struct audio_stream *stream)
7166{
7167 struct stream_in *in = (struct stream_in *)stream;
7168 struct audio_device *adev = in->dev;
7169 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307170 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7171 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007172 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307173
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007174 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007175 if (!in->standby && in->is_st_session) {
7176 ALOGD("%s: sound trigger pcm stop lab", __func__);
7177 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007178 if (adev->num_va_sessions > 0)
7179 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007180 in->standby = 1;
7181 }
7182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007183 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007184 if (adev->adm_deregister_stream)
7185 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7186
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007187 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007189 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007190 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007191 voice_extn_compress_voip_close_input_stream(stream);
7192 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007193 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7194 do_stop = in->capture_started;
7195 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007196 if (in->mmap_shared_memory_fd >= 0) {
7197 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7198 __func__, in->mmap_shared_memory_fd);
7199 close(in->mmap_shared_memory_fd);
7200 in->mmap_shared_memory_fd = -1;
7201 }
Zhou Songa8895042016-07-05 17:54:22 +08007202 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307203 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307204 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007205 }
7206
Arun Mirpuri5d170872019-03-26 13:21:31 -07007207 if (in->pcm) {
7208 ATRACE_BEGIN("pcm_in_close");
7209 pcm_close(in->pcm);
7210 ATRACE_END();
7211 in->pcm = NULL;
7212 }
7213
Carter Hsu2e429db2019-05-14 18:50:52 +08007214 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007215 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007216
George Gao3018ede2019-10-23 13:23:00 -07007217 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7218 if (adev->num_va_sessions > 0)
7219 adev->num_va_sessions--;
7220 }
Quinn Malef6050362019-01-30 15:55:40 -08007221
Eric Laurent150dbfe2013-02-27 14:31:02 -08007222 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007223 }
7224 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007225 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007226 return status;
7227}
7228
Aalique Grahame22e49102018-12-18 14:23:57 -08007229static int in_dump(const struct audio_stream *stream,
7230 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007231{
Aalique Grahame22e49102018-12-18 14:23:57 -08007232 struct stream_in *in = (struct stream_in *)stream;
7233
7234 // We try to get the lock for consistency,
7235 // but it isn't necessary for these variables.
7236 // If we're not in standby, we may be blocked on a read.
7237 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7238 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7239 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7240 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307241#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007242 char buffer[256]; // for statistics formatting
7243 if (in->start_latency_ms.n > 0) {
7244 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7245 dprintf(fd, " Start latency ms: %s\n", buffer);
7246 }
Dechen Chai22768452021-07-30 09:29:16 +05307247#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007248 if (locked) {
7249 pthread_mutex_unlock(&in->lock);
7250 }
Dechen Chai22768452021-07-30 09:29:16 +05307251#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007252 // dump error info
7253 (void)error_log_dump(
7254 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307255#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007256 return 0;
7257}
7258
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307259static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7260{
7261 if (!stream || !parms)
7262 return;
7263
7264 struct stream_in *in = (struct stream_in *)stream;
7265 struct audio_device *adev = in->dev;
7266
7267 card_status_t status;
7268 int card;
7269 if (parse_snd_card_status(parms, &card, &status) < 0)
7270 return;
7271
7272 pthread_mutex_lock(&adev->lock);
7273 bool valid_cb = (card == adev->snd_card);
7274 pthread_mutex_unlock(&adev->lock);
7275
7276 if (!valid_cb)
7277 return;
7278
7279 lock_input_stream(in);
7280 if (in->card_status != status)
7281 in->card_status = status;
7282 pthread_mutex_unlock(&in->lock);
7283
7284 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7285 use_case_table[in->usecase],
7286 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7287
7288 // a better solution would be to report error back to AF and let
7289 // it put the stream to standby
7290 if (status == CARD_STATUS_OFFLINE)
7291 in_standby(&in->stream.common);
7292
7293 return;
7294}
7295
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007296int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007297 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007298 audio_source_t source)
7299{
7300 struct audio_device *adev = in->dev;
7301 int ret = 0;
7302
7303 lock_input_stream(in);
7304 pthread_mutex_lock(&adev->lock);
7305
7306 /* no audio source uses val == 0 */
7307 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7308 in->source = source;
7309 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7310 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7311 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7312 (in->config.rate == 8000 || in->config.rate == 16000 ||
7313 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7314 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7315 ret = voice_extn_compress_voip_open_input_stream(in);
7316 if (ret != 0) {
7317 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7318 __func__, ret);
7319 }
7320 }
7321 }
7322
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007323 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7324 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007325 // Workaround: If routing to an non existing usb device, fail gracefully
7326 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007327 struct str_parms *usb_addr =
7328 str_parms_create_str(get_usb_device_address(devices));
7329 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007330 !audio_extn_usb_connected(NULL)) {
7331 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007332 ret = -ENOSYS;
7333 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007334 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007335 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007336 if (!in->standby && !in->is_st_session) {
7337 ALOGV("update input routing change");
7338 // inform adm before actual routing to prevent glitches.
7339 if (adev->adm_on_routing_change) {
7340 adev->adm_on_routing_change(adev->adm_data,
7341 in->capture_handle);
7342 ret = select_devices(adev, in->usecase);
7343 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7344 adev->adm_routing_changed = true;
7345 }
7346 }
7347 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007348 if (usb_addr)
7349 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007350 }
7351 pthread_mutex_unlock(&adev->lock);
7352 pthread_mutex_unlock(&in->lock);
7353
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007354 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007355 return ret;
7356}
7357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007358static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7359{
7360 struct stream_in *in = (struct stream_in *)stream;
7361 struct audio_device *adev = in->dev;
7362 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307364 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007365
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307366 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367 parms = str_parms_create_str(kvpairs);
7368
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307369 if (!parms)
7370 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007371 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007372 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007373
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307374 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7375 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307376 strlcpy(in->profile, value, sizeof(in->profile));
7377 ALOGV("updating stream profile with value '%s'", in->profile);
7378 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7379 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007380 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307381 in->sample_rate, in->bit_width,
7382 in->profile, &in->app_type_cfg);
7383 }
7384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007385 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007386 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007387
7388 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307389error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307390 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007391}
7392
7393static char* in_get_parameters(const struct audio_stream *stream,
7394 const char *keys)
7395{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007396 struct stream_in *in = (struct stream_in *)stream;
7397 struct str_parms *query = str_parms_create_str(keys);
7398 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007399 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007400
7401 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007402 if (reply) {
7403 str_parms_destroy(reply);
7404 }
7405 if (query) {
7406 str_parms_destroy(query);
7407 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007408 ALOGE("in_get_parameters: failed to create query or reply");
7409 return NULL;
7410 }
7411
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007412 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007413
7414 voice_extn_in_get_parameters(in, query, reply);
7415
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007416 stream_get_parameter_channels(query, reply,
7417 &in->supported_channel_masks[0]);
7418 stream_get_parameter_formats(query, reply,
7419 &in->supported_formats[0]);
7420 stream_get_parameter_rates(query, reply,
7421 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007422 str = str_parms_to_str(reply);
7423 str_parms_destroy(query);
7424 str_parms_destroy(reply);
7425
7426 ALOGV("%s: exit: returns - %s", __func__, str);
7427 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007428}
7429
Aalique Grahame22e49102018-12-18 14:23:57 -08007430static int in_set_gain(struct audio_stream_in *stream,
7431 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007432{
Aalique Grahame22e49102018-12-18 14:23:57 -08007433 struct stream_in *in = (struct stream_in *)stream;
7434 char mixer_ctl_name[128];
7435 struct mixer_ctl *ctl;
7436 int ctl_value;
7437
7438 ALOGV("%s: gain %f", __func__, gain);
7439
7440 if (stream == NULL)
7441 return -EINVAL;
7442
7443 /* in_set_gain() only used to silence MMAP capture for now */
7444 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7445 return -ENOSYS;
7446
7447 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7448
7449 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7450 if (!ctl) {
7451 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7452 __func__, mixer_ctl_name);
7453 return -ENOSYS;
7454 }
7455
7456 if (gain < RECORD_GAIN_MIN)
7457 gain = RECORD_GAIN_MIN;
7458 else if (gain > RECORD_GAIN_MAX)
7459 gain = RECORD_GAIN_MAX;
7460 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7461
7462 mixer_ctl_set_value(ctl, 0, ctl_value);
7463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007464 return 0;
7465}
7466
7467static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7468 size_t bytes)
7469{
7470 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307471
7472 if (in == NULL) {
7473 ALOGE("%s: stream_in ptr is NULL", __func__);
7474 return -EINVAL;
7475 }
7476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007477 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307478 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307479 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007480
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007481 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307482
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007483 if (in->is_st_session) {
7484 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7485 /* Read from sound trigger HAL */
7486 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007487 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007488 if (adev->num_va_sessions < UINT_MAX)
7489 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007490 in->standby = 0;
7491 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007492 pthread_mutex_unlock(&in->lock);
7493 return bytes;
7494 }
7495
Haynes Mathew George16081042017-05-31 17:16:49 -07007496 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7497 ret = -ENOSYS;
7498 goto exit;
7499 }
7500
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007501 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7502 !in->standby && adev->adm_routing_changed) {
7503 ret = -ENOSYS;
7504 goto exit;
7505 }
7506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007507 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007508 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7509
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007510 pthread_mutex_lock(&adev->lock);
7511 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7512 ret = voice_extn_compress_voip_start_input_stream(in);
7513 else
7514 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007515 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7516 if (adev->num_va_sessions < UINT_MAX)
7517 adev->num_va_sessions++;
7518 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007519 pthread_mutex_unlock(&adev->lock);
7520 if (ret != 0) {
7521 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007522 }
7523 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307524#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007525 // log startup time in ms.
7526 simple_stats_log(
7527 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307528#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007530
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307531 /* Avoid read if capture_stopped is set */
7532 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7533 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7534 ret = -EINVAL;
7535 goto exit;
7536 }
7537
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007538 // what's the duration requested by the client?
7539 long ns = 0;
7540
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307541 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007542 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7543 in->config.rate;
7544
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007545 ret = request_in_focus(in, ns);
7546 if (ret != 0)
7547 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007548 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007549
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307550 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307551 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7552 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307553 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007554 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307555 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007556 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007557 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007558 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007559 } else if (audio_extn_ffv_get_stream() == in) {
7560 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307561 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007562 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307563 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7564 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7565 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7566 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307567 ret = -EINVAL;
7568 goto exit;
7569 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307570 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307571 ret = -errno;
7572 }
7573 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307574 /* bytes read is always set to bytes for non compress usecases */
7575 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007576 }
7577
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007578 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007580 /*
Quinn Malef6050362019-01-30 15:55:40 -08007581 * Instead of writing zeroes here, we could trust the hardware to always
7582 * provide zeroes when muted. This is also muted with voice recognition
7583 * usecases so that other clients do not have access to voice recognition
7584 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007585 */
Quinn Malef6050362019-01-30 15:55:40 -08007586 if ((ret == 0 && voice_get_mic_mute(adev) &&
7587 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007588 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7589 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007590 (adev->num_va_sessions &&
7591 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7592 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7593 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007594 memset(buffer, 0, bytes);
7595
7596exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307597 frame_size = audio_stream_in_frame_size(stream);
7598 if (frame_size > 0)
7599 in->frames_read += bytes_read/frame_size;
7600
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007601 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307602 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007603 pthread_mutex_unlock(&in->lock);
7604
7605 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307606 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307607 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307608 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307609 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307610 in->standby = true;
7611 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307612 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307613 bytes_read = bytes;
7614 memset(buffer, 0, bytes);
7615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007616 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007617 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7618 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007619 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307620 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307621 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007622 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307623 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007624}
7625
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007626static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007627{
7628 return 0;
7629}
7630
Aalique Grahame22e49102018-12-18 14:23:57 -08007631static int in_get_capture_position(const struct audio_stream_in *stream,
7632 int64_t *frames, int64_t *time)
7633{
7634 if (stream == NULL || frames == NULL || time == NULL) {
7635 return -EINVAL;
7636 }
7637 struct stream_in *in = (struct stream_in *)stream;
7638 int ret = -ENOSYS;
7639
7640 lock_input_stream(in);
7641 // note: ST sessions do not close the alsa pcm driver synchronously
7642 // on standby. Therefore, we may return an error even though the
7643 // pcm stream is still opened.
7644 if (in->standby) {
7645 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7646 "%s stream in standby but pcm not NULL for non ST session", __func__);
7647 goto exit;
7648 }
7649 if (in->pcm) {
7650 struct timespec timestamp;
7651 unsigned int avail;
7652 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7653 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007654 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007655 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307656 //Adjustment accounts for A2dp decoder latency for recording usecase
7657 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7658 if (is_a2dp_in_device_type(&in->device_list))
7659 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007660 ret = 0;
7661 }
7662 }
7663exit:
7664 pthread_mutex_unlock(&in->lock);
7665 return ret;
7666}
7667
Carter Hsu2e429db2019-05-14 18:50:52 +08007668static int in_update_effect_list(bool add, effect_handle_t effect,
7669 struct listnode *head)
7670{
7671 struct listnode *node;
7672 struct in_effect_list *elist = NULL;
7673 struct in_effect_list *target = NULL;
7674 int ret = 0;
7675
7676 if (!head)
7677 return ret;
7678
7679 list_for_each(node, head) {
7680 elist = node_to_item(node, struct in_effect_list, list);
7681 if (elist->handle == effect) {
7682 target = elist;
7683 break;
7684 }
7685 }
7686
7687 if (add) {
7688 if (target) {
7689 ALOGD("effect %p already exist", effect);
7690 return ret;
7691 }
7692
7693 target = (struct in_effect_list *)
7694 calloc(1, sizeof(struct in_effect_list));
7695
7696 if (!target) {
7697 ALOGE("%s:fail to allocate memory", __func__);
7698 return -ENOMEM;
7699 }
7700
7701 target->handle = effect;
7702 list_add_tail(head, &target->list);
7703 } else {
7704 if (target) {
7705 list_remove(&target->list);
7706 free(target);
7707 }
7708 }
7709
7710 return ret;
7711}
7712
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007713static int add_remove_audio_effect(const struct audio_stream *stream,
7714 effect_handle_t effect,
7715 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007716{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007717 struct stream_in *in = (struct stream_in *)stream;
7718 int status = 0;
7719 effect_descriptor_t desc;
7720
7721 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007722 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7723
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007724 if (status != 0)
7725 return status;
7726
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007727 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007728 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007729 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007730 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7731 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007732 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007733
7734 in_update_effect_list(enable, effect, &in->aec_list);
7735 enable = !list_empty(&in->aec_list);
7736 if (enable == in->enable_aec)
7737 goto exit;
7738
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007739 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007740 ALOGD("AEC enable %d", enable);
7741
Aalique Grahame22e49102018-12-18 14:23:57 -08007742 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7743 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7744 in->dev->enable_voicerx = enable;
7745 struct audio_usecase *usecase;
7746 struct listnode *node;
7747 list_for_each(node, &in->dev->usecase_list) {
7748 usecase = node_to_item(node, struct audio_usecase, list);
7749 if (usecase->type == PCM_PLAYBACK)
7750 select_devices(in->dev, usecase->id);
7751 }
7752 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007753 if (!in->standby) {
7754 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7755 select_devices(in->dev, in->usecase);
7756 }
7757
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007758 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007759 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7760
7761 in_update_effect_list(enable, effect, &in->ns_list);
7762 enable = !list_empty(&in->ns_list);
7763 if (enable == in->enable_ns)
7764 goto exit;
7765
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007766 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007767 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007768 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007769 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307770 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007771 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007772 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7773 select_devices(in->dev, in->usecase);
7774 } else
7775 select_devices(in->dev, in->usecase);
7776 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007777 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007778exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007779 pthread_mutex_unlock(&in->dev->lock);
7780 pthread_mutex_unlock(&in->lock);
7781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007782 return 0;
7783}
7784
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007785static int in_add_audio_effect(const struct audio_stream *stream,
7786 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007787{
Eric Laurent994a6932013-07-17 11:51:42 -07007788 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007789 return add_remove_audio_effect(stream, effect, true);
7790}
7791
7792static int in_remove_audio_effect(const struct audio_stream *stream,
7793 effect_handle_t effect)
7794{
Eric Laurent994a6932013-07-17 11:51:42 -07007795 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007796 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007797}
7798
Haynes Mathew George16081042017-05-31 17:16:49 -07007799static int in_stop(const struct audio_stream_in* stream)
7800{
7801 struct stream_in *in = (struct stream_in *)stream;
7802 struct audio_device *adev = in->dev;
7803
7804 int ret = -ENOSYS;
7805 ALOGV("%s", __func__);
7806 pthread_mutex_lock(&adev->lock);
7807 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7808 in->capture_started && in->pcm != NULL) {
7809 pcm_stop(in->pcm);
7810 ret = stop_input_stream(in);
7811 in->capture_started = false;
7812 }
7813 pthread_mutex_unlock(&adev->lock);
7814 return ret;
7815}
7816
7817static int in_start(const struct audio_stream_in* stream)
7818{
7819 struct stream_in *in = (struct stream_in *)stream;
7820 struct audio_device *adev = in->dev;
7821 int ret = -ENOSYS;
7822
7823 ALOGV("%s in %p", __func__, in);
7824 pthread_mutex_lock(&adev->lock);
7825 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7826 !in->capture_started && in->pcm != NULL) {
7827 if (!in->capture_started) {
7828 ret = start_input_stream(in);
7829 if (ret == 0) {
7830 in->capture_started = true;
7831 }
7832 }
7833 }
7834 pthread_mutex_unlock(&adev->lock);
7835 return ret;
7836}
7837
Phil Burke0a86d12019-02-16 22:28:11 -08007838// Read offset for the positional timestamp from a persistent vendor property.
7839// This is to workaround apparent inaccuracies in the timing information that
7840// is used by the AAudio timing model. The inaccuracies can cause glitches.
7841static int64_t in_get_mmap_time_offset() {
7842 const int32_t kDefaultOffsetMicros = 0;
7843 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007844 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007845 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7846 return mmap_time_offset_micros * (int64_t)1000;
7847}
7848
Haynes Mathew George16081042017-05-31 17:16:49 -07007849static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7850 int32_t min_size_frames,
7851 struct audio_mmap_buffer_info *info)
7852{
7853 struct stream_in *in = (struct stream_in *)stream;
7854 struct audio_device *adev = in->dev;
7855 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007856 unsigned int offset1 = 0;
7857 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007858 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007859 uint32_t mmap_size = 0;
7860 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007861
7862 pthread_mutex_lock(&adev->lock);
7863 ALOGV("%s in %p", __func__, in);
7864
Sharad Sanglec6f32552018-05-04 16:15:38 +05307865 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007866 CARD_STATUS_OFFLINE == adev->card_status ||
7867 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307868 ALOGW("in->card_status or adev->card_status offline, try again");
7869 ret = -EIO;
7870 goto exit;
7871 }
7872
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307873 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007874 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7875 ret = -EINVAL;
7876 goto exit;
7877 }
7878 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7879 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7880 ALOGV("%s in %p", __func__, in);
7881 ret = -ENOSYS;
7882 goto exit;
7883 }
7884 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7885 if (in->pcm_device_id < 0) {
7886 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7887 __func__, in->pcm_device_id, in->usecase);
7888 ret = -EINVAL;
7889 goto exit;
7890 }
7891
7892 adjust_mmap_period_count(&in->config, min_size_frames);
7893
7894 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7895 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7896 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7897 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307898 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307899 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7900 in->card_status = CARD_STATUS_OFFLINE;
7901 adev->card_status = CARD_STATUS_OFFLINE;
7902 ret = -EIO;
7903 goto exit;
7904 }
7905
Haynes Mathew George16081042017-05-31 17:16:49 -07007906 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7907 step = "open";
7908 ret = -ENODEV;
7909 goto exit;
7910 }
7911
7912 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7913 if (ret < 0) {
7914 step = "begin";
7915 goto exit;
7916 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007917
juyuchen626833d2019-06-04 16:48:02 +08007918 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007919 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7920 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7921 info->burst_size_frames = in->config.period_size;
7922 ret = platform_get_mmap_data_fd(adev->platform,
7923 in->pcm_device_id, 1 /*capture*/,
7924 &info->shared_memory_fd,
7925 &mmap_size);
7926 if (ret < 0) {
7927 // Fall back to non exclusive mode
7928 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7929 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007930 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7931 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7932
Arun Mirpuri5d170872019-03-26 13:21:31 -07007933 if (mmap_size < buffer_size) {
7934 step = "mmap";
7935 goto exit;
7936 }
juyuchen626833d2019-06-04 16:48:02 +08007937 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007938 }
7939
7940 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007941
7942 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7943 if (ret < 0) {
7944 step = "commit";
7945 goto exit;
7946 }
7947
Phil Burke0a86d12019-02-16 22:28:11 -08007948 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7949
Haynes Mathew George16081042017-05-31 17:16:49 -07007950 in->standby = false;
7951 ret = 0;
7952
7953 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7954 __func__, info->shared_memory_address, info->buffer_size_frames);
7955
7956exit:
7957 if (ret != 0) {
7958 if (in->pcm == NULL) {
7959 ALOGE("%s: %s - %d", __func__, step, ret);
7960 } else {
7961 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7962 pcm_close(in->pcm);
7963 in->pcm = NULL;
7964 }
7965 }
7966 pthread_mutex_unlock(&adev->lock);
7967 return ret;
7968}
7969
7970static int in_get_mmap_position(const struct audio_stream_in *stream,
7971 struct audio_mmap_position *position)
7972{
7973 struct stream_in *in = (struct stream_in *)stream;
7974 ALOGVV("%s", __func__);
7975 if (position == NULL) {
7976 return -EINVAL;
7977 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307978 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007979 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307980 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007981 return -ENOSYS;
7982 }
7983 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307984 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007985 return -ENOSYS;
7986 }
7987 struct timespec ts = { 0, 0 };
7988 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7989 if (ret < 0) {
7990 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307991 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007992 return ret;
7993 }
Phil Burke0a86d12019-02-16 22:28:11 -08007994 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7995 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307996 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007997 return 0;
7998}
7999
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308000static int in_get_active_microphones(const struct audio_stream_in *stream,
8001 struct audio_microphone_characteristic_t *mic_array,
8002 size_t *mic_count) {
8003 struct stream_in *in = (struct stream_in *)stream;
8004 struct audio_device *adev = in->dev;
8005 ALOGVV("%s", __func__);
8006
8007 lock_input_stream(in);
8008 pthread_mutex_lock(&adev->lock);
8009 int ret = platform_get_active_microphones(adev->platform,
8010 audio_channel_count_from_in_mask(in->channel_mask),
8011 in->usecase, mic_array, mic_count);
8012 pthread_mutex_unlock(&adev->lock);
8013 pthread_mutex_unlock(&in->lock);
8014
8015 return ret;
8016}
8017
8018static int adev_get_microphones(const struct audio_hw_device *dev,
8019 struct audio_microphone_characteristic_t *mic_array,
8020 size_t *mic_count) {
8021 struct audio_device *adev = (struct audio_device *)dev;
8022 ALOGVV("%s", __func__);
8023
8024 pthread_mutex_lock(&adev->lock);
8025 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8026 pthread_mutex_unlock(&adev->lock);
8027
8028 return ret;
8029}
juyuchendb308c22019-01-21 11:57:17 -07008030
8031static void in_update_sink_metadata(struct audio_stream_in *stream,
8032 const struct sink_metadata *sink_metadata) {
8033
8034 if (stream == NULL
8035 || sink_metadata == NULL
8036 || sink_metadata->tracks == NULL) {
8037 return;
8038 }
8039
8040 int error = 0;
8041 struct stream_in *in = (struct stream_in *)stream;
8042 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008043 struct listnode devices;
8044
8045 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008046
8047 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008048 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008049
8050 lock_input_stream(in);
8051 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008052 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008053
Zhou Song503196b2021-07-23 17:31:05 +08008054 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8055 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8056 !list_empty(&devices) &&
8057 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008058 /* Use the rx device from afe-proxy record to route voice call because
8059 there is no routing if tx device is on primary hal and rx device
8060 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008061 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008062
8063 if (!voice_is_call_state_active(adev)) {
8064 if (adev->mode == AUDIO_MODE_IN_CALL) {
8065 adev->current_call_output = adev->voice_tx_output;
8066 error = voice_start_call(adev);
8067 if (error != 0)
8068 ALOGE("%s: start voice call failed %d", __func__, error);
8069 }
8070 } else {
8071 adev->current_call_output = adev->voice_tx_output;
8072 voice_update_devices_for_all_voice_usecases(adev);
8073 }
8074 }
8075
Zhenlin Lian4f947842022-05-14 15:50:52 +05308076 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008077 pthread_mutex_unlock(&adev->lock);
8078 pthread_mutex_unlock(&in->lock);
8079}
8080
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308081int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008082 audio_io_handle_t handle,
8083 audio_devices_t devices,
8084 audio_output_flags_t flags,
8085 struct audio_config *config,
8086 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008087 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008088{
8089 struct audio_device *adev = (struct audio_device *)dev;
8090 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308091 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008092 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008093 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308094 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008095 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8096 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8097 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8098 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008099 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008100 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8101 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008102 bool force_haptic_path =
8103 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008104 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008105#ifdef AUDIO_GKI_ENABLED
8106 __s32 *generic_dec;
8107#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008108 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008109
kunleizdff872d2018-08-20 14:40:33 +08008110 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008111 is_usb_dev = false;
8112 devices = AUDIO_DEVICE_OUT_SPEAKER;
8113 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8114 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008115 if (config->format == AUDIO_FORMAT_DEFAULT)
8116 config->format = AUDIO_FORMAT_PCM_16_BIT;
8117 if (config->sample_rate == 0)
8118 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8119 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8120 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008121 }
8122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008123 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008125 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8126
Mingming Yin3a941d42016-02-17 18:08:05 -08008127 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008128 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8129 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308130
8131
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008132 if (!out) {
8133 return -ENOMEM;
8134 }
8135
Haynes Mathew George204045b2015-02-25 20:32:03 -08008136 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008137 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008138 pthread_mutexattr_init(&latch_attr);
8139 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8140 pthread_mutex_init(&out->latch_lock, &latch_attr);
8141 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008142 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008143 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008145 if (devices == AUDIO_DEVICE_NONE)
8146 devices = AUDIO_DEVICE_OUT_SPEAKER;
8147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008148 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008149 list_init(&out->device_list);
8150 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008151 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008152 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008153 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308154 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308155 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8156 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8157 else
8158 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008159 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008160 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008161 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308162 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308163 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008164 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008165 out->hal_output_suspend_supported = 0;
8166 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308167 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308168 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308169 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008170 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008171
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308172 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308173 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008174 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8175
Aalique Grahame22e49102018-12-18 14:23:57 -08008176 if (direct_dev &&
8177 (audio_is_linear_pcm(out->format) ||
8178 config->format == AUDIO_FORMAT_DEFAULT) &&
8179 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8180 audio_format_t req_format = config->format;
8181 audio_channel_mask_t req_channel_mask = config->channel_mask;
8182 uint32_t req_sample_rate = config->sample_rate;
8183
8184 pthread_mutex_lock(&adev->lock);
8185 if (is_hdmi) {
8186 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8187 ret = read_hdmi_sink_caps(out);
8188 if (config->sample_rate == 0)
8189 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8190 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8191 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8192 if (config->format == AUDIO_FORMAT_DEFAULT)
8193 config->format = AUDIO_FORMAT_PCM_16_BIT;
8194 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008195 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8196 &config->format,
8197 &out->supported_formats[0],
8198 MAX_SUPPORTED_FORMATS,
8199 &config->channel_mask,
8200 &out->supported_channel_masks[0],
8201 MAX_SUPPORTED_CHANNEL_MASKS,
8202 &config->sample_rate,
8203 &out->supported_sample_rates[0],
8204 MAX_SUPPORTED_SAMPLE_RATES);
8205 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008206 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008207
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008208 pthread_mutex_unlock(&adev->lock);
8209 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008210 if (ret == -ENOSYS) {
8211 /* ignore and go with default */
8212 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008213 }
8214 // For MMAP NO IRQ, allow conversions in ADSP
8215 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8216 goto error_open;
8217 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008218 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008219 goto error_open;
8220 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008221
8222 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8223 config->sample_rate = req_sample_rate;
8224 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8225 config->channel_mask = req_channel_mask;
8226 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8227 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008228 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008229
8230 out->sample_rate = config->sample_rate;
8231 out->channel_mask = config->channel_mask;
8232 out->format = config->format;
8233 if (is_hdmi) {
8234 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8235 out->config = pcm_config_hdmi_multi;
8236 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8237 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8238 out->config = pcm_config_mmap_playback;
8239 out->stream.start = out_start;
8240 out->stream.stop = out_stop;
8241 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8242 out->stream.get_mmap_position = out_get_mmap_position;
8243 } else {
8244 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8245 out->config = pcm_config_hifi;
8246 }
8247
8248 out->config.rate = out->sample_rate;
8249 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8250 if (is_hdmi) {
8251 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8252 audio_bytes_per_sample(out->format));
8253 }
8254 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008255 }
8256
Derek Chenf6318be2017-06-12 17:16:24 -04008257 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008258 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008259 /* extract car audio stream index */
8260 out->car_audio_stream =
8261 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8262 if (out->car_audio_stream < 0) {
8263 ALOGE("%s: invalid car audio stream %x",
8264 __func__, out->car_audio_stream);
8265 ret = -EINVAL;
8266 goto error_open;
8267 }
Derek Chen5f67a942020-02-24 23:08:13 -08008268 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008269 }
8270
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008271 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008272 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008273 if (!voice_extn_is_compress_voip_supported()) {
8274 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8275 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008276 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308277 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008278 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8279 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008280 out->volume_l = INVALID_OUT_VOLUME;
8281 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008282
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008283 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008284 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008285 uint32_t channel_count =
8286 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308287 out->config.channels = channel_count;
8288
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008289 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8290 out->sample_rate, out->format,
8291 channel_count, false);
8292 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8293 if (frame_size != 0)
8294 out->config.period_size = buffer_size / frame_size;
8295 else
8296 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008297 }
8298 } else {
8299 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8300 voice_extn_compress_voip_is_active(out->dev)) &&
8301 (voice_extn_compress_voip_is_config_supported(config))) {
8302 ret = voice_extn_compress_voip_open_output_stream(out);
8303 if (ret != 0) {
8304 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8305 __func__, ret);
8306 goto error_open;
8307 }
Sujin Panicker19027262019-09-16 18:28:06 +05308308 } else {
8309 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8310 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008311 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008312 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008313 } else if (audio_is_linear_pcm(out->format) &&
8314 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8315 out->channel_mask = config->channel_mask;
8316 out->sample_rate = config->sample_rate;
8317 out->format = config->format;
8318 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8319 // does this change?
8320 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8321 out->config.rate = config->sample_rate;
8322 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8323 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8324 audio_bytes_per_sample(config->format));
8325 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008326 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308327 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308328 pthread_mutex_lock(&adev->lock);
8329 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8330 pthread_mutex_unlock(&adev->lock);
8331
8332 // reject offload during card offline to allow
8333 // fallback to s/w paths
8334 if (offline) {
8335 ret = -ENODEV;
8336 goto error_open;
8337 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008339 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8340 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8341 ALOGE("%s: Unsupported Offload information", __func__);
8342 ret = -EINVAL;
8343 goto error_open;
8344 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008345
Atul Khare3fa6e542017-08-09 00:56:17 +05308346 if (config->offload_info.format == 0)
8347 config->offload_info.format = config->format;
8348 if (config->offload_info.sample_rate == 0)
8349 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008350
Mingming Yin90310102013-11-13 16:57:00 -08008351 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308352 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008353 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008354 ret = -EINVAL;
8355 goto error_open;
8356 }
8357
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008358 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8359 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8360 (audio_extn_passthru_is_passthrough_stream(out)) &&
8361 !((config->sample_rate == 48000) ||
8362 (config->sample_rate == 96000) ||
8363 (config->sample_rate == 192000))) {
8364 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8365 __func__, config->sample_rate, config->offload_info.format);
8366 ret = -EINVAL;
8367 goto error_open;
8368 }
8369
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008370 out->compr_config.codec = (struct snd_codec *)
8371 calloc(1, sizeof(struct snd_codec));
8372
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008373 if (!out->compr_config.codec) {
8374 ret = -ENOMEM;
8375 goto error_open;
8376 }
8377
Dhananjay Kumarac341582017-02-23 23:42:25 +05308378 out->stream.pause = out_pause;
8379 out->stream.resume = out_resume;
8380 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308381 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308382 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008383 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308384 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008385 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308386 } else {
8387 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8388 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008389 }
vivek mehta446c3962015-09-14 10:57:35 -07008390
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308391 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8392 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008393#ifdef AUDIO_GKI_ENABLED
8394 /* out->compr_config.codec->reserved[1] is for flags */
8395 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8396#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308397 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008398#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308399 }
8400
vivek mehta446c3962015-09-14 10:57:35 -07008401 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008402 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008403 config->format == 0 && config->sample_rate == 0 &&
8404 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008405 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008406 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8407 } else {
8408 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8409 ret = -EEXIST;
8410 goto error_open;
8411 }
vivek mehta446c3962015-09-14 10:57:35 -07008412 }
8413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008414 if (config->offload_info.channel_mask)
8415 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008416 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008417 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008418 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008419 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308420 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008421 ret = -EINVAL;
8422 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008423 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008424
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008425 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008426 out->sample_rate = config->offload_info.sample_rate;
8427
Mingming Yin3ee55c62014-08-04 14:23:35 -07008428 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008429
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308430 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308431 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308432 audio_extn_dolby_send_ddp_endp_params(adev);
8433 audio_extn_dolby_set_dmid(adev);
8434 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008435
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008436 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008437 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008438 out->compr_config.codec->bit_rate =
8439 config->offload_info.bit_rate;
8440 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308441 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008442 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308443 /* Update bit width only for non passthrough usecases.
8444 * For passthrough usecases, the output will always be opened @16 bit
8445 */
8446 if (!audio_extn_passthru_is_passthrough_stream(out))
8447 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308448
8449 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008450#ifdef AUDIO_GKI_ENABLED
8451 /* out->compr_config.codec->reserved[1] is for flags */
8452 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8453 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8454#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308455 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8456 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008457#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308458
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008459 /*TODO: Do we need to change it for passthrough */
8460 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008461
Manish Dewangana6fc5442015-08-24 20:30:31 +05308462 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8463 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308464 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308465 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308466 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8467 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308468
8469 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8470 AUDIO_FORMAT_PCM) {
8471
8472 /*Based on platform support, configure appropriate alsa format for corresponding
8473 *hal input format.
8474 */
8475 out->compr_config.codec->format = hal_format_to_alsa(
8476 config->offload_info.format);
8477
Ashish Jain83a6cc22016-06-28 14:34:17 +05308478 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308479 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308480 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308481
Dhananjay Kumarac341582017-02-23 23:42:25 +05308482 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308483 *hal input format and alsa format might differ based on platform support.
8484 */
8485 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308486 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308487
8488 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8489
Deeraj Soman93155a62019-09-30 19:00:37 +05308490 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8491 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8492 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8493 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8494 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308495
Ashish Jainf1eaa582016-05-23 20:54:24 +05308496 /* Check if alsa session is configured with the same format as HAL input format,
8497 * if not then derive correct fragment size needed to accomodate the
8498 * conversion of HAL input format to alsa format.
8499 */
8500 audio_extn_utils_update_direct_pcm_fragment_size(out);
8501
8502 /*if hal input and output fragment size is different this indicates HAL input format is
8503 *not same as the alsa format
8504 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308505 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308506 /*Allocate a buffer to convert input data to the alsa configured format.
8507 *size of convert buffer is equal to the size required to hold one fragment size
8508 *worth of pcm data, this is because flinger does not write more than fragment_size
8509 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308510 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8511 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308512 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8513 ret = -ENOMEM;
8514 goto error_open;
8515 }
8516 }
8517 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8518 out->compr_config.fragment_size =
8519 audio_extn_passthru_get_buffer_size(&config->offload_info);
8520 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8521 } else {
8522 out->compr_config.fragment_size =
8523 platform_get_compress_offload_buffer_size(&config->offload_info);
8524 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8525 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008526
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308527 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8528 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8529 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008530 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8531#ifdef AUDIO_GKI_ENABLED
8532 generic_dec =
8533 &(out->compr_config.codec->options.generic.reserved[1]);
8534 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8535 AUDIO_OUTPUT_BIT_WIDTH;
8536#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308537 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008538#endif
8539 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008540
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308541 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8542 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8543 }
8544
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008545 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8546 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008547
Manish Dewangan69426c82017-01-30 17:35:36 +05308548 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8549 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8550 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8551 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8552 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8553 } else {
8554 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8555 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008556
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308557 memset(&out->channel_map_param, 0,
8558 sizeof(struct audio_out_channel_map_param));
8559
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008560 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308561 out->send_next_track_params = false;
8562 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008563 out->offload_state = OFFLOAD_STATE_IDLE;
8564 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008565 out->writeAt.tv_sec = 0;
8566 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008567
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008568 audio_extn_dts_create_state_notifier_node(out->usecase);
8569
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008570 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8571 __func__, config->offload_info.version,
8572 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308573
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308574 /* Check if DSD audio format is supported in codec
8575 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308576 */
8577
8578 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308579 (!platform_check_codec_dsd_support(adev->platform) ||
8580 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308581 ret = -EINVAL;
8582 goto error_open;
8583 }
8584
Ashish Jain5106d362016-05-11 19:23:33 +05308585 /* Disable gapless if any of the following is true
8586 * passthrough playback
8587 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308588 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308589 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308590 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308591 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008592 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308593 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308594 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308595 check_and_set_gapless_mode(adev, false);
8596 } else
8597 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008598
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308599 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008600 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8601 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308602 if (config->format == AUDIO_FORMAT_DSD) {
8603 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008604#ifdef AUDIO_GKI_ENABLED
8605 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8606 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8607#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308608 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008609#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308610 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008611
8612 create_offload_callback_thread(out);
8613
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008614 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008615 switch (config->sample_rate) {
8616 case 0:
8617 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8618 break;
8619 case 8000:
8620 case 16000:
8621 case 48000:
8622 out->sample_rate = config->sample_rate;
8623 break;
8624 default:
8625 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8626 config->sample_rate);
8627 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8628 ret = -EINVAL;
8629 goto error_open;
8630 }
8631 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8632 switch (config->channel_mask) {
8633 case AUDIO_CHANNEL_NONE:
8634 case AUDIO_CHANNEL_OUT_STEREO:
8635 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8636 break;
8637 default:
8638 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8639 config->channel_mask);
8640 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8641 ret = -EINVAL;
8642 goto error_open;
8643 }
8644 switch (config->format) {
8645 case AUDIO_FORMAT_DEFAULT:
8646 case AUDIO_FORMAT_PCM_16_BIT:
8647 out->format = AUDIO_FORMAT_PCM_16_BIT;
8648 break;
8649 default:
8650 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8651 config->format);
8652 config->format = AUDIO_FORMAT_PCM_16_BIT;
8653 ret = -EINVAL;
8654 goto error_open;
8655 }
8656
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308657 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008658 if (ret != 0) {
8659 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008660 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008661 goto error_open;
8662 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008663 } else if (is_single_device_type_equal(&out->device_list,
8664 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008665 switch (config->sample_rate) {
8666 case 0:
8667 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8668 break;
8669 case 8000:
8670 case 16000:
8671 case 48000:
8672 out->sample_rate = config->sample_rate;
8673 break;
8674 default:
8675 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8676 config->sample_rate);
8677 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8678 ret = -EINVAL;
8679 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008680 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008681 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8682 switch (config->channel_mask) {
8683 case AUDIO_CHANNEL_NONE:
8684 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8685 break;
8686 case AUDIO_CHANNEL_OUT_STEREO:
8687 out->channel_mask = config->channel_mask;
8688 break;
8689 default:
8690 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8691 config->channel_mask);
8692 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8693 ret = -EINVAL;
8694 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008695 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008696 switch (config->format) {
8697 case AUDIO_FORMAT_DEFAULT:
8698 out->format = AUDIO_FORMAT_PCM_16_BIT;
8699 break;
8700 case AUDIO_FORMAT_PCM_16_BIT:
8701 out->format = config->format;
8702 break;
8703 default:
8704 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8705 config->format);
8706 config->format = AUDIO_FORMAT_PCM_16_BIT;
8707 ret = -EINVAL;
8708 break;
8709 }
8710 if (ret != 0)
8711 goto error_open;
8712
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008713 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8714 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008715 out->config.rate = out->sample_rate;
8716 out->config.channels =
8717 audio_channel_count_from_out_mask(out->channel_mask);
8718 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008719 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008720 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308721 unsigned int channels = 0;
8722 /*Update config params to default if not set by the caller*/
8723 if (config->sample_rate == 0)
8724 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8725 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8726 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8727 if (config->format == AUDIO_FORMAT_DEFAULT)
8728 config->format = AUDIO_FORMAT_PCM_16_BIT;
8729
8730 channels = audio_channel_count_from_out_mask(out->channel_mask);
8731
Varun Balaraje49253e2017-07-06 19:48:56 +05308732 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8733 out->usecase = get_interactive_usecase(adev);
8734 out->config = pcm_config_low_latency;
8735 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308736 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008737 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8738 out->flags);
8739 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008740 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8741 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8742 out->config = pcm_config_mmap_playback;
8743 out->stream.start = out_start;
8744 out->stream.stop = out_stop;
8745 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8746 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308747 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8748 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008749 out->hal_output_suspend_supported =
8750 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8751 out->dynamic_pm_qos_config_supported =
8752 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8753 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008754 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8755 } else {
8756 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8757 //the mixer path will be a string similar to "low-latency-playback resume"
8758 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8759 strlcat(out->pm_qos_mixer_path,
8760 " resume", MAX_MIXER_PATH_LEN);
8761 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8762 out->pm_qos_mixer_path);
8763 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308764 out->config = pcm_config_low_latency;
8765 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8766 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8767 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308768 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8769 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8770 if (out->config.period_size <= 0) {
8771 ALOGE("Invalid configuration period size is not valid");
8772 ret = -EINVAL;
8773 goto error_open;
8774 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008775 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8776 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8777 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008778 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8779 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8780 out->config = pcm_config_haptics_audio;
8781 if (force_haptic_path)
8782 adev->haptics_config = pcm_config_haptics_audio;
8783 else
8784 adev->haptics_config = pcm_config_haptics;
8785
Meng Wangd08ce322020-04-02 08:59:20 +08008786 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008787 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8788
8789 if (force_haptic_path) {
8790 out->config.channels = 1;
8791 adev->haptics_config.channels = 1;
8792 } else
8793 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 -08008794 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008795 ret = audio_extn_auto_hal_open_output_stream(out);
8796 if (ret) {
8797 ALOGE("%s: Failed to open output stream for bus device", __func__);
8798 ret = -EINVAL;
8799 goto error_open;
8800 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308801 } else {
8802 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008803 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8804 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308805 }
8806 out->hal_ip_format = format = out->format;
8807 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8808 out->hal_op_format = pcm_format_to_hal(out->config.format);
8809 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8810 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008811 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308812 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308813 if (out->hal_ip_format != out->hal_op_format) {
8814 uint32_t buffer_size = out->config.period_size *
8815 format_to_bitwidth_table[out->hal_op_format] *
8816 out->config.channels;
8817 out->convert_buffer = calloc(1, buffer_size);
8818 if (out->convert_buffer == NULL){
8819 ALOGE("Allocation failed for convert buffer for size %d",
8820 out->compr_config.fragment_size);
8821 ret = -ENOMEM;
8822 goto error_open;
8823 }
8824 ALOGD("Convert buffer allocated of size %d", buffer_size);
8825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008826 }
8827
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008828 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8829 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308830
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008831 /* TODO remove this hardcoding and check why width is zero*/
8832 if (out->bit_width == 0)
8833 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308834 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008835 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008836 &out->device_list, out->flags,
8837 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308838 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308839 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008840 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008841 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8842 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008843 if(adev->primary_output == NULL)
8844 adev->primary_output = out;
8845 else {
8846 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008847 ret = -EEXIST;
8848 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008849 }
8850 }
8851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008852 /* Check if this usecase is already existing */
8853 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008854 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8855 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008856 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008857 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008858 ret = -EEXIST;
8859 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008860 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008862 pthread_mutex_unlock(&adev->lock);
8863
8864 out->stream.common.get_sample_rate = out_get_sample_rate;
8865 out->stream.common.set_sample_rate = out_set_sample_rate;
8866 out->stream.common.get_buffer_size = out_get_buffer_size;
8867 out->stream.common.get_channels = out_get_channels;
8868 out->stream.common.get_format = out_get_format;
8869 out->stream.common.set_format = out_set_format;
8870 out->stream.common.standby = out_standby;
8871 out->stream.common.dump = out_dump;
8872 out->stream.common.set_parameters = out_set_parameters;
8873 out->stream.common.get_parameters = out_get_parameters;
8874 out->stream.common.add_audio_effect = out_add_audio_effect;
8875 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8876 out->stream.get_latency = out_get_latency;
8877 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008878#ifdef NO_AUDIO_OUT
8879 out->stream.write = out_write_for_no_output;
8880#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008881 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008882#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008883 out->stream.get_render_position = out_get_render_position;
8884 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008885 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008886
Haynes Mathew George16081042017-05-31 17:16:49 -07008887 if (out->realtime)
8888 out->af_period_multiplier = af_period_multiplier;
8889 else
8890 out->af_period_multiplier = 1;
8891
Andy Hunga1f48fa2019-07-01 18:14:53 -07008892 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008894 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008895 out->volume_l = PLAYBACK_GAIN_MAX;
8896 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008897 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008898 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008899
8900 config->format = out->stream.common.get_format(&out->stream.common);
8901 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8902 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308903 register_format(out->format, out->supported_formats);
8904 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8905 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008906
Dechen Chai22768452021-07-30 09:29:16 +05308907#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008908 out->error_log = error_log_create(
8909 ERROR_LOG_ENTRIES,
8910 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308911#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308912 /*
8913 By locking output stream before registering, we allow the callback
8914 to update stream's state only after stream's initial state is set to
8915 adev state.
8916 */
8917 lock_output_stream(out);
8918 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8919 pthread_mutex_lock(&adev->lock);
8920 out->card_status = adev->card_status;
8921 pthread_mutex_unlock(&adev->lock);
8922 pthread_mutex_unlock(&out->lock);
8923
Aalique Grahame22e49102018-12-18 14:23:57 -08008924 stream_app_type_cfg_init(&out->app_type_cfg);
8925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008926 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308927 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008928 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008929
8930 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8931 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8932 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008933 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308934 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008935 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008936 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308937 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8938 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008939 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8940 out->usecase, PCM_PLAYBACK);
8941 hdlr_stream_cfg.flags = out->flags;
8942 hdlr_stream_cfg.type = PCM_PLAYBACK;
8943 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8944 &hdlr_stream_cfg);
8945 if (ret) {
8946 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8947 out->adsp_hdlr_stream_handle = NULL;
8948 }
8949 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308950 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8951 is_direct_passthough, false);
8952 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8953 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008954 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008955 if (ret < 0) {
8956 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8957 out->ip_hdlr_handle = NULL;
8958 }
8959 }
Derek Chenf939fb72018-11-13 13:34:41 -08008960
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008961 ret = io_streams_map_insert(adev, &out->stream.common,
8962 out->handle, AUDIO_PATCH_HANDLE_NONE);
8963 if (ret != 0)
8964 goto error_open;
8965
Susan Wang6dd13092021-01-25 10:27:11 -05008966 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008967
8968 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008969 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008970 pthread_mutex_unlock(&adev->lock);
8971
Eric Laurent994a6932013-07-17 11:51:42 -07008972 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008973 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008974
8975error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308976 if (out->convert_buffer)
8977 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008978 free(out);
8979 *stream_out = NULL;
8980 ALOGD("%s: exit: ret %d", __func__, ret);
8981 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008982}
8983
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308984void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008985 struct audio_stream_out *stream)
8986{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008987 struct stream_out *out = (struct stream_out *)stream;
8988 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008989 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008990
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008991 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308992
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008993 io_streams_map_remove(adev, out->handle);
8994
Susan Wang6dd13092021-01-25 10:27:11 -05008995 // remove out_ctxt early to prevent the stream
8996 // being opened in a race condition
8997 pthread_mutex_lock(&adev->lock);
8998 list_remove(&out->out_ctxt.list);
8999 pthread_mutex_unlock(&adev->lock);
9000
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309001 // must deregister from sndmonitor first to prevent races
9002 // between the callback and close_stream
9003 audio_extn_snd_mon_unregister_listener(out);
9004
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009005 /* close adsp hdrl session before standby */
9006 if (out->adsp_hdlr_stream_handle) {
9007 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9008 if (ret)
9009 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9010 out->adsp_hdlr_stream_handle = NULL;
9011 }
9012
Manish Dewangan21a850a2017-08-14 12:03:55 +05309013 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009014 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9015 out->ip_hdlr_handle = NULL;
9016 }
9017
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009018 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309019 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009020 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309021 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309022 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009023 if(ret != 0)
9024 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9025 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009026 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009027 out_standby(&stream->common);
9028
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009029 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009030 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009031 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009032 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009033 if (out->compr_config.codec != NULL)
9034 free(out->compr_config.codec);
9035 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009036
Zhou Songbaddf9f2020-11-20 13:57:39 +08009037 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309038
Varun Balaraje49253e2017-07-06 19:48:56 +05309039 if (is_interactive_usecase(out->usecase))
9040 free_interactive_usecase(adev, out->usecase);
9041
Ashish Jain83a6cc22016-06-28 14:34:17 +05309042 if (out->convert_buffer != NULL) {
9043 free(out->convert_buffer);
9044 out->convert_buffer = NULL;
9045 }
9046
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009047 if (adev->voice_tx_output == out)
9048 adev->voice_tx_output = NULL;
9049
Dechen Chai22768452021-07-30 09:29:16 +05309050#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009051 error_log_destroy(out->error_log);
9052 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309053#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309054 if (adev->primary_output == out)
9055 adev->primary_output = NULL;
9056
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009057 pthread_cond_destroy(&out->cond);
9058 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009059 pthread_mutex_destroy(&out->pre_lock);
9060 pthread_mutex_destroy(&out->latch_lock);
9061 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009062
9063 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309064 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009065 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009066 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009067 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009068}
9069
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009070void in_set_power_policy(uint8_t enable)
9071{
9072 struct listnode *node;
9073
9074 ALOGD("%s: Enter, state %d", __func__, enable);
9075
9076 pthread_mutex_lock(&adev->lock);
9077 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9078 pthread_mutex_unlock(&adev->lock);
9079
9080 if (!enable) {
9081 list_for_each(node, &adev->active_inputs_list) {
9082 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9083 streams_input_ctxt_t,
9084 list);
9085 struct stream_in *in = in_ctxt->input;
9086 in_standby(&in->stream.common);
9087 }
9088 }
9089
9090 ALOGD("%s: Exit", __func__);
9091}
9092
9093void out_set_power_policy(uint8_t enable)
9094{
9095 struct listnode *node;
9096
9097 ALOGD("%s: Enter, state %d", __func__, enable);
9098
9099 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309100 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009101 pthread_mutex_unlock(&adev->lock);
9102
9103 if (!enable) {
9104 list_for_each(node, &adev->active_outputs_list) {
9105 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9106 streams_output_ctxt_t,
9107 list);
9108 struct stream_out *out = out_ctxt->output;
9109 out_on_error(&out->stream.common);
9110 }
9111 }
9112
9113 ALOGD("%s: Exit", __func__);
9114}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009115static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9116{
9117 struct audio_device *adev = (struct audio_device *)dev;
9118 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009119 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009120 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009121 int ret;
9122 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009123 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009124 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009125 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009126
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009127 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009128 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009129
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309130 if (!parms)
9131 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309132
Derek Chen6f293672019-04-01 01:40:24 -07009133 /* notify adev and input/output streams on the snd card status */
9134 adev_snd_mon_cb((void *)adev, parms);
9135
Weiyin Jiang24f55292020-12-22 14:35:46 +08009136 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9137 if (ret >= 0) {
9138 list_for_each(node, &adev->active_outputs_list) {
9139 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9140 streams_output_ctxt_t,
9141 list);
9142 out_snd_mon_cb((void *)out_ctxt->output, parms);
9143 }
Derek Chen6f293672019-04-01 01:40:24 -07009144
Weiyin Jiang24f55292020-12-22 14:35:46 +08009145 list_for_each(node, &adev->active_inputs_list) {
9146 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9147 streams_input_ctxt_t,
9148 list);
9149 in_snd_mon_cb((void *)in_ctxt->input, parms);
9150 }
Derek Chen6f293672019-04-01 01:40:24 -07009151 }
9152
Zhou Songd6d71752019-05-21 18:08:51 +08009153 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309154 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9155 if (ret >= 0) {
9156 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009157 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309158 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309159 /*
9160 * When ever BT_SCO=ON arrives, make sure to route
9161 * all use cases to SCO device, otherwise due to delay in
9162 * BT_SCO=ON and lack of synchronization with create audio patch
9163 * request for SCO device, some times use case not routed properly to
9164 * SCO device
9165 */
9166 struct audio_usecase *usecase;
9167 struct listnode *node;
9168 list_for_each(node, &adev->usecase_list) {
9169 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309170 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309171 (!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 +05309172 ALOGD("BT_SCO ON, switch all in use case to it");
9173 select_devices(adev, usecase->id);
9174 }
Mingshu Pangef517202021-04-22 10:35:00 +08009175 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9176 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309177 (!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 +05309178 ALOGD("BT_SCO ON, switch all out use case to it");
9179 select_devices(adev, usecase->id);
9180 }
9181 }
9182 }
9183 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309184 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009185 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009186 }
9187 }
9188
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009189 status = voice_set_parameters(adev, parms);
9190 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009191 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009192
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009193 status = platform_set_parameters(adev->platform, parms);
9194 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009195 goto done;
9196
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009197 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9198 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009199 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009200 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9201 adev->bluetooth_nrec = true;
9202 else
9203 adev->bluetooth_nrec = false;
9204 }
9205
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009206 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9207 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009208 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9209 adev->screen_off = false;
9210 else
9211 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009212 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009213 }
9214
Eric Laurent4b084132018-10-19 17:33:43 -07009215 ret = str_parms_get_int(parms, "rotation", &val);
9216 if (ret >= 0) {
9217 bool reverse_speakers = false;
9218 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9219 switch (val) {
9220 // FIXME: note that the code below assumes that the speakers are in the correct placement
9221 // relative to the user when the device is rotated 90deg from its default rotation. This
9222 // assumption is device-specific, not platform-specific like this code.
9223 case 270:
9224 reverse_speakers = true;
9225 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9226 break;
9227 case 0:
9228 case 180:
9229 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9230 break;
9231 case 90:
9232 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9233 break;
9234 default:
9235 ALOGE("%s: unexpected rotation of %d", __func__, val);
9236 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009237 }
Eric Laurent4b084132018-10-19 17:33:43 -07009238 if (status == 0) {
9239 // check and set swap
9240 // - check if orientation changed and speaker active
9241 // - set rotation and cache the rotation value
9242 adev->camera_orientation =
9243 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9244 if (!audio_extn_is_maxx_audio_enabled())
9245 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9246 }
9247 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009248
Mingming Yin514a8bc2014-07-29 15:22:21 -07009249 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9250 if (ret >= 0) {
9251 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9252 adev->bt_wb_speech_enabled = true;
9253 else
9254 adev->bt_wb_speech_enabled = false;
9255 }
9256
Zhou Song12c29502019-03-16 10:37:18 +08009257 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9258 if (ret >= 0) {
9259 val = atoi(value);
9260 adev->swb_speech_mode = val;
9261 }
9262
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009263 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9264 if (ret >= 0) {
9265 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309266 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009267 if (audio_is_output_device(val) &&
9268 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009269 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009270 platform_get_controller_stream_from_params(parms, &controller, &stream);
9271 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9272 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009273 if (ret < 0) {
9274 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309275 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009276 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009277 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309278 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009279 /*
9280 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9281 * Per AudioPolicyManager, USB device is higher priority than WFD.
9282 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9283 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9284 * starting voice call on USB
9285 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009286 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309287 if (ret >= 0)
9288 audio_extn_usb_add_device(device, atoi(value));
9289
Zhou Song6f862822017-11-06 17:27:57 +08009290 if (!audio_extn_usb_is_tunnel_supported()) {
9291 ALOGV("detected USB connect .. disable proxy");
9292 adev->allow_afe_proxy_usage = false;
9293 }
Zhou Song503196b2021-07-23 17:31:05 +08009294 } else if (audio_is_hearing_aid_out_device(device) &&
9295 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9296 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009297 }
9298 }
9299
9300 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9301 if (ret >= 0) {
9302 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309303 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009304 /*
9305 * The HDMI / Displayport disconnect handling has been moved to
9306 * audio extension to ensure that its parameters are not
9307 * invalidated prior to updating sysfs of the disconnect event
9308 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9309 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309310 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009311 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309312 if (ret >= 0)
9313 audio_extn_usb_remove_device(device, atoi(value));
9314
Zhou Song6f862822017-11-06 17:27:57 +08009315 if (!audio_extn_usb_is_tunnel_supported()) {
9316 ALOGV("detected USB disconnect .. enable proxy");
9317 adev->allow_afe_proxy_usage = true;
9318 }
Zhou Song503196b2021-07-23 17:31:05 +08009319 } else if (audio_is_hearing_aid_out_device(device)) {
9320 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009321 }
9322 }
9323
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009324 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009325
9326 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009327 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309328 struct audio_usecase *usecase;
9329 struct listnode *node;
9330 list_for_each(node, &adev->usecase_list) {
9331 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009332 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9333 continue;
9334
9335 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309336 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309337 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309338 ALOGD("Switching to speaker and muting the stream before select_devices");
9339 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309340 //force device switch to re configure encoder
9341 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309342 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009343 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309344 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309345 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009346 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009347 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009348 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009349 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9350 reassign_device_list(&usecase->stream.out->device_list,
9351 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9352 check_a2dp_restore_l(adev, usecase->stream.out, true);
9353 break;
9354 }
9355 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309356 }
9357 }
9358 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009359
9360 //handle vr audio setparam
9361 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9362 value, sizeof(value));
9363 if (ret >= 0) {
9364 ALOGI("Setting vr mode to be %s", value);
9365 if (!strncmp(value, "true", 4)) {
9366 adev->vr_audio_mode_enabled = true;
9367 ALOGI("Setting vr mode to true");
9368 } else if (!strncmp(value, "false", 5)) {
9369 adev->vr_audio_mode_enabled = false;
9370 ALOGI("Setting vr mode to false");
9371 } else {
9372 ALOGI("wrong vr mode set");
9373 }
9374 }
9375
Eric Laurent4b084132018-10-19 17:33:43 -07009376 //FIXME: to be replaced by proper video capture properties API
9377 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9378 if (ret >= 0) {
9379 int camera_facing = CAMERA_FACING_BACK;
9380 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9381 camera_facing = CAMERA_FACING_FRONT;
9382 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9383 camera_facing = CAMERA_FACING_BACK;
9384 else {
9385 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9386 goto done;
9387 }
9388 adev->camera_orientation =
9389 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9390 struct audio_usecase *usecase;
9391 struct listnode *node;
9392 list_for_each(node, &adev->usecase_list) {
9393 usecase = node_to_item(node, struct audio_usecase, list);
9394 struct stream_in *in = usecase->stream.in;
9395 if (usecase->type == PCM_CAPTURE && in != NULL &&
9396 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9397 select_devices(adev, in->usecase);
9398 }
9399 }
9400 }
9401
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309402 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009403done:
9404 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009405 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309406error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009407 ALOGV("%s: exit with code(%d)", __func__, status);
9408 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009409}
9410
9411static char* adev_get_parameters(const struct audio_hw_device *dev,
9412 const char *keys)
9413{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309414 ALOGD("%s:%s", __func__, keys);
9415
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009416 struct audio_device *adev = (struct audio_device *)dev;
9417 struct str_parms *reply = str_parms_create();
9418 struct str_parms *query = str_parms_create_str(keys);
9419 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309420 char value[256] = {0};
9421 int ret = 0;
9422
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009423 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009424 if (reply) {
9425 str_parms_destroy(reply);
9426 }
9427 if (query) {
9428 str_parms_destroy(query);
9429 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009430 ALOGE("adev_get_parameters: failed to create query or reply");
9431 return NULL;
9432 }
9433
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009434 //handle vr audio getparam
9435
9436 ret = str_parms_get_str(query,
9437 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9438 value, sizeof(value));
9439
9440 if (ret >= 0) {
9441 bool vr_audio_enabled = false;
9442 pthread_mutex_lock(&adev->lock);
9443 vr_audio_enabled = adev->vr_audio_mode_enabled;
9444 pthread_mutex_unlock(&adev->lock);
9445
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009446 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009447
9448 if (vr_audio_enabled) {
9449 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9450 "true");
9451 goto exit;
9452 } else {
9453 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9454 "false");
9455 goto exit;
9456 }
9457 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009458
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009459 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009460 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009461 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009462 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009463 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009464 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309465 pthread_mutex_unlock(&adev->lock);
9466
Naresh Tannirud7205b62014-06-20 02:54:48 +05309467exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009468 str = str_parms_to_str(reply);
9469 str_parms_destroy(query);
9470 str_parms_destroy(reply);
9471
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009472 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009473 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009474}
9475
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009476static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009477{
9478 return 0;
9479}
9480
9481static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9482{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009483 int ret;
9484 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009485
9486 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9487
Haynes Mathew George5191a852013-09-11 14:19:36 -07009488 pthread_mutex_lock(&adev->lock);
9489 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009490 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009491 pthread_mutex_unlock(&adev->lock);
9492 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009493}
9494
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009495static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9496 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009497{
9498 return -ENOSYS;
9499}
9500
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009501static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9502 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009503{
9504 return -ENOSYS;
9505}
9506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009507static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9508 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009509{
9510 return -ENOSYS;
9511}
9512
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009513static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9514 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009515{
9516 return -ENOSYS;
9517}
9518
9519static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9520{
9521 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009522 struct listnode *node;
9523 struct audio_usecase *usecase = NULL;
9524 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009526 pthread_mutex_lock(&adev->lock);
9527 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309528 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9529 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009530 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009531 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309532 adev->current_call_output = adev->primary_output;
9533 voice_start_call(adev);
9534 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009535 (mode == AUDIO_MODE_NORMAL ||
9536 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009537 list_for_each(node, &adev->usecase_list) {
9538 usecase = node_to_item(node, struct audio_usecase, list);
9539 if (usecase->type == VOICE_CALL)
9540 break;
9541 }
9542 if (usecase &&
9543 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9544 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9545 true);
9546 if (ret != 0) {
9547 /* default service interval was successfully updated,
9548 reopen USB backend with new service interval */
9549 check_usecases_codec_backend(adev,
9550 usecase,
9551 usecase->out_snd_device);
9552 }
9553 }
9554
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009555 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009556 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009557 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009558 // restore device for other active usecases after stop call
9559 list_for_each(node, &adev->usecase_list) {
9560 usecase = node_to_item(node, struct audio_usecase, list);
9561 select_devices(adev, usecase->id);
9562 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009564 }
9565 pthread_mutex_unlock(&adev->lock);
9566 return 0;
9567}
9568
9569static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9570{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009571 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009572 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009573
9574 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009575 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009576 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009577
Derek Chend2530072014-11-24 12:39:14 -08009578 if (adev->ext_hw_plugin)
9579 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009580
9581 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009582 pthread_mutex_unlock(&adev->lock);
9583
9584 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009585}
9586
9587static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9588{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009589 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009590 return 0;
9591}
9592
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009593static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009594 const struct audio_config *config)
9595{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009596 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009597
Aalique Grahame22e49102018-12-18 14:23:57 -08009598 /* Don't know if USB HIFI in this context so use true to be conservative */
9599 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9600 true /*is_usb_hifi */) != 0)
9601 return 0;
9602
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009603 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9604 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009605}
9606
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009607static bool adev_input_allow_hifi_record(struct audio_device *adev,
9608 audio_devices_t devices,
9609 audio_input_flags_t flags,
9610 audio_source_t source) {
9611 const bool allowed = true;
9612
9613 if (!audio_is_usb_in_device(devices))
9614 return !allowed;
9615
9616 switch (flags) {
9617 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009618 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009619 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9620 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009621 default:
9622 return !allowed;
9623 }
9624
9625 switch (source) {
9626 case AUDIO_SOURCE_DEFAULT:
9627 case AUDIO_SOURCE_MIC:
9628 case AUDIO_SOURCE_UNPROCESSED:
9629 break;
9630 default:
9631 return !allowed;
9632 }
9633
9634 switch (adev->mode) {
9635 case 0:
9636 break;
9637 default:
9638 return !allowed;
9639 }
9640
9641 return allowed;
9642}
9643
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009644static int adev_update_voice_comm_input_stream(struct stream_in *in,
9645 struct audio_config *config)
9646{
9647 bool valid_rate = (config->sample_rate == 8000 ||
9648 config->sample_rate == 16000 ||
9649 config->sample_rate == 32000 ||
9650 config->sample_rate == 48000);
9651 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9652
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009653 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009654 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009655 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9656 in->config = default_pcm_config_voip_copp;
9657 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9658 DEFAULT_VOIP_BUF_DURATION_MS,
9659 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009660 } else {
9661 ALOGW("%s No valid input in voip, use defaults"
9662 "sample rate %u, channel mask 0x%X",
9663 __func__, config->sample_rate, in->channel_mask);
9664 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009665 in->config.rate = config->sample_rate;
9666 in->sample_rate = config->sample_rate;
9667 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009668 //XXX needed for voice_extn_compress_voip_open_input_stream
9669 in->config.rate = config->sample_rate;
9670 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309671 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009672 voice_extn_compress_voip_is_active(in->dev)) &&
9673 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9674 valid_rate && valid_ch) {
9675 voice_extn_compress_voip_open_input_stream(in);
9676 // update rate entries to match config from AF
9677 in->config.rate = config->sample_rate;
9678 in->sample_rate = config->sample_rate;
9679 } else {
9680 ALOGW("%s compress voip not active, use defaults", __func__);
9681 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009682 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009683 return 0;
9684}
9685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009686static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009687 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009688 audio_devices_t devices,
9689 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009690 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309691 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009692 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009693 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009694{
9695 struct audio_device *adev = (struct audio_device *)dev;
9696 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009697 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009698 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009699 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309700 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009701 bool is_usb_dev = audio_is_usb_in_device(devices);
9702 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9703 devices,
9704 flags,
9705 source);
Andy Hung94320602018-10-29 18:31:12 -07009706 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9707 " sample_rate %u, channel_mask %#x, format %#x",
9708 __func__, flags, is_usb_dev, may_use_hifi_record,
9709 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309710
kunleizdff872d2018-08-20 14:40:33 +08009711 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009712 is_usb_dev = false;
9713 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9714 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9715 __func__, devices);
9716 }
9717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009718 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009719
9720 if (!(is_usb_dev && may_use_hifi_record)) {
9721 if (config->sample_rate == 0)
9722 config->sample_rate = 48000;
9723 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9724 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9725 if (config->format == AUDIO_FORMAT_DEFAULT)
9726 config->format = AUDIO_FORMAT_PCM_16_BIT;
9727
9728 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9729
Aalique Grahame22e49102018-12-18 14:23:57 -08009730 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9731 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009732 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309733 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009734
9735 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009736
9737 if (!in) {
9738 ALOGE("failed to allocate input stream");
9739 return -ENOMEM;
9740 }
9741
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309742 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309743 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9744 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009745 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009746 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009748 in->stream.common.get_sample_rate = in_get_sample_rate;
9749 in->stream.common.set_sample_rate = in_set_sample_rate;
9750 in->stream.common.get_buffer_size = in_get_buffer_size;
9751 in->stream.common.get_channels = in_get_channels;
9752 in->stream.common.get_format = in_get_format;
9753 in->stream.common.set_format = in_set_format;
9754 in->stream.common.standby = in_standby;
9755 in->stream.common.dump = in_dump;
9756 in->stream.common.set_parameters = in_set_parameters;
9757 in->stream.common.get_parameters = in_get_parameters;
9758 in->stream.common.add_audio_effect = in_add_audio_effect;
9759 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9760 in->stream.set_gain = in_set_gain;
9761 in->stream.read = in_read;
9762 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009763 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309764 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009765 in->stream.set_microphone_direction = in_set_microphone_direction;
9766 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009767 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009768
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009769 list_init(&in->device_list);
9770 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009771 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009772 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009773 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009774 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009775 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009776 in->bit_width = 16;
9777 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009778 in->direction = MIC_DIRECTION_UNSPECIFIED;
9779 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009780 list_init(&in->aec_list);
9781 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009782 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009783
Andy Hung94320602018-10-29 18:31:12 -07009784 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009785 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9786 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9787 /* Force channel config requested to mono if incall
9788 record is being requested for only uplink/downlink */
9789 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9790 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9791 ret = -EINVAL;
9792 goto err_open;
9793 }
9794 }
9795
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009796 if (is_usb_dev && may_use_hifi_record) {
9797 /* HiFi record selects an appropriate format, channel, rate combo
9798 depending on sink capabilities*/
9799 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9800 &config->format,
9801 &in->supported_formats[0],
9802 MAX_SUPPORTED_FORMATS,
9803 &config->channel_mask,
9804 &in->supported_channel_masks[0],
9805 MAX_SUPPORTED_CHANNEL_MASKS,
9806 &config->sample_rate,
9807 &in->supported_sample_rates[0],
9808 MAX_SUPPORTED_SAMPLE_RATES);
9809 if (ret != 0) {
9810 ret = -EINVAL;
9811 goto err_open;
9812 }
9813 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009814 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309815 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309816 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9817 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9818 in->config.format = PCM_FORMAT_S32_LE;
9819 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309820 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9821 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9822 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9823 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9824 bool ret_error = false;
9825 in->bit_width = 24;
9826 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9827 from HAL is 24_packed and 8_24
9828 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9829 24_packed return error indicating supported format is 24_packed
9830 *> In case of any other source requesting 24 bit or float return error
9831 indicating format supported is 16 bit only.
9832
9833 on error flinger will retry with supported format passed
9834 */
9835 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9836 (source != AUDIO_SOURCE_CAMCORDER)) {
9837 config->format = AUDIO_FORMAT_PCM_16_BIT;
9838 if (config->sample_rate > 48000)
9839 config->sample_rate = 48000;
9840 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009841 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9842 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309843 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9844 ret_error = true;
9845 }
9846
9847 if (ret_error) {
9848 ret = -EINVAL;
9849 goto err_open;
9850 }
9851 }
9852
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009853 in->channel_mask = config->channel_mask;
9854 in->format = config->format;
9855
9856 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309857
Huicheng Liu1404ba12020-09-11 01:03:25 -04009858 /* validate bus device address */
9859 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9860 /* extract car audio stream index */
9861 in->car_audio_stream =
9862 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9863 if (in->car_audio_stream < 0) {
9864 ALOGE("%s: invalid car audio stream %x",
9865 __func__, in->car_audio_stream);
9866 ret = -EINVAL;
9867 goto err_open;
9868 }
9869 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009870 ret = audio_extn_auto_hal_open_input_stream(in);
9871 if (ret) {
9872 ALOGE("%s: Failed to open input stream for bus device", __func__);
9873 ret = -EINVAL;
9874 goto err_open;
9875 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009876 }
9877
Susan Wange3959562021-03-11 11:50:26 -05009878 /* reassign use case for echo reference stream on automotive platforms */
9879 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9880 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9881 }
9882
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309883 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309884 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9885 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9886 else {
9887 ret = -EINVAL;
9888 goto err_open;
9889 }
9890 }
9891
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309892 if ((config->sample_rate == 48000 ||
9893 config->sample_rate == 32000 ||
9894 config->sample_rate == 24000 ||
9895 config->sample_rate == 16000 ||
9896 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309897 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9898 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009899 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9900 is_low_latency = true;
9901#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309902 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9903 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9904 else
9905 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009906#endif
9907 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009908 if (!in->realtime) {
9909 in->config = pcm_config_audio_capture;
9910 frame_size = audio_stream_in_frame_size(&in->stream);
9911 buffer_size = get_input_buffer_size(config->sample_rate,
9912 config->format,
9913 channel_count,
9914 is_low_latency);
9915 in->config.period_size = buffer_size / frame_size;
9916 in->config.rate = config->sample_rate;
9917 in->af_period_multiplier = 1;
9918 } else {
9919 // period size is left untouched for rt mode playback
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309920 switch(config->sample_rate)
9921 {
9922 case 48000:
9923 in->config = pcm_config_audio_capture_rt_48KHz;
9924 break;
9925 case 32000:
9926 in->config = pcm_config_audio_capture_rt_32KHz;
9927 break;
9928 case 24000:
9929 in->config = pcm_config_audio_capture_rt_24KHz;
9930 break;
9931 case 16000:
9932 in->config = pcm_config_audio_capture_rt_16KHz;
9933 break;
9934 case 8000:
9935 in->config = pcm_config_audio_capture_rt_8KHz;
9936 break;
9937 default:
9938 in->config = pcm_config_audio_capture_rt_48KHz;
9939 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009940 in->af_period_multiplier = af_period_multiplier;
9941 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009942 }
9943
Susan Wangb803cb52021-10-14 12:03:36 -04009944 /* Additional sample rates added below must also be present
9945 in audio_policy_configuration.xml for mmap_no_irq_in */
9946 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9947 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009948 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009949 config->sample_rate == 32000 ||
9950 config->sample_rate == 48000);
9951 if (valid_mmap_record_rate &&
9952 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009953 in->realtime = 0;
9954 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9955 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009956 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009957 in->stream.start = in_start;
9958 in->stream.stop = in_stop;
9959 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9960 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309961 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009962 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009963 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009964 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9965 in->config = pcm_config_audio_capture;
9966 frame_size = audio_stream_in_frame_size(&in->stream);
9967 buffer_size = get_input_buffer_size(config->sample_rate,
9968 config->format,
9969 channel_count,
9970 false /*is_low_latency*/);
9971 in->config.period_size = buffer_size / frame_size;
9972 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009973 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009974 switch (config->format) {
9975 case AUDIO_FORMAT_PCM_32_BIT:
9976 in->bit_width = 32;
9977 break;
9978 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9979 case AUDIO_FORMAT_PCM_8_24_BIT:
9980 in->bit_width = 24;
9981 break;
9982 default:
9983 in->bit_width = 16;
9984 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009985 } else if (is_single_device_type_equal(&in->device_list,
9986 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9987 is_single_device_type_equal(&in->device_list,
9988 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009989 if (config->sample_rate == 0)
9990 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9991 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9992 config->sample_rate != 8000) {
9993 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9994 ret = -EINVAL;
9995 goto err_open;
9996 }
9997 if (config->format == AUDIO_FORMAT_DEFAULT)
9998 config->format = AUDIO_FORMAT_PCM_16_BIT;
9999 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10000 config->format = AUDIO_FORMAT_PCM_16_BIT;
10001 ret = -EINVAL;
10002 goto err_open;
10003 }
10004
10005 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010006 if (adev->ha_proxy_enable &&
10007 is_single_device_type_equal(&in->device_list,
10008 AUDIO_DEVICE_IN_TELEPHONY_RX))
10009 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010010 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010011 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010012 in->af_period_multiplier = 1;
10013 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010014 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010015 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10016 (config->sample_rate == 8000 ||
10017 config->sample_rate == 16000 ||
10018 config->sample_rate == 32000 ||
10019 config->sample_rate == 48000) &&
10020 channel_count == 1) {
10021 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10022 in->config = pcm_config_audio_capture;
10023 frame_size = audio_stream_in_frame_size(&in->stream);
10024 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10025 config->sample_rate,
10026 config->format,
10027 channel_count, false /*is_low_latency*/);
10028 in->config.period_size = buffer_size / frame_size;
10029 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10030 in->config.rate = config->sample_rate;
10031 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010032 } else if (in->realtime) {
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010033 switch(config->sample_rate)
10034 {
10035 case 48000:
10036 in->config = pcm_config_audio_capture_rt_48KHz;
10037 break;
10038 case 32000:
10039 in->config = pcm_config_audio_capture_rt_32KHz;
10040 break;
10041 case 24000:
10042 in->config = pcm_config_audio_capture_rt_24KHz;
10043 break;
10044 case 16000:
10045 in->config = pcm_config_audio_capture_rt_16KHz;
10046 break;
10047 case 8000:
10048 in->config = pcm_config_audio_capture_rt_8KHz;
10049 break;
10050 default:
10051 in->config = pcm_config_audio_capture_rt_48KHz;
10052 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010053 in->config.format = pcm_format_from_audio_format(config->format);
10054 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -070010055 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010056 int ret_val;
10057 pthread_mutex_lock(&adev->lock);
10058 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10059 in, config, &channel_mask_updated);
10060 pthread_mutex_unlock(&adev->lock);
10061
10062 if (!ret_val) {
10063 if (channel_mask_updated == true) {
10064 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10065 __func__, config->channel_mask);
10066 ret = -EINVAL;
10067 goto err_open;
10068 }
10069 ALOGD("%s: created multi-channel session succesfully",__func__);
10070 } else if (audio_extn_compr_cap_enabled() &&
10071 audio_extn_compr_cap_format_supported(config->format) &&
10072 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10073 audio_extn_compr_cap_init(in);
10074 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010075 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010076 if (ret)
10077 goto err_open;
10078 } else {
10079 in->config = pcm_config_audio_capture;
10080 in->config.rate = config->sample_rate;
10081 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010082 in->format = config->format;
10083 frame_size = audio_stream_in_frame_size(&in->stream);
10084 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010085 config->format,
10086 channel_count,
10087 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010088 /* prevent division-by-zero */
10089 if (frame_size == 0) {
10090 ALOGE("%s: Error frame_size==0", __func__);
10091 ret = -EINVAL;
10092 goto err_open;
10093 }
10094
Revathi Uddarajud2634032017-12-07 14:42:34 +053010095 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010096 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010097
Revathi Uddarajud2634032017-12-07 14:42:34 +053010098 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10099 /* optionally use VOIP usecase depending on config(s) */
10100 ret = adev_update_voice_comm_input_stream(in, config);
10101 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010102
Revathi Uddarajud2634032017-12-07 14:42:34 +053010103 if (ret) {
10104 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10105 goto err_open;
10106 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010107 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010108
10109 /* assign concurrent capture usecase if record has to caried out from
10110 * actual hardware input source */
10111 if (audio_extn_is_concurrent_capture_enabled() &&
10112 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010113 /* Acquire lock to avoid two concurrent use cases initialized to
10114 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010115
Samyak Jainc37062f2019-04-25 18:41:06 +053010116 if (in->usecase == USECASE_AUDIO_RECORD) {
10117 pthread_mutex_lock(&adev->lock);
10118 if (!(adev->pcm_record_uc_state)) {
10119 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10120 adev->pcm_record_uc_state = 1;
10121 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010122 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10123 in->usecase = get_record_usecase(adev);
10124 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010125 } else {
10126 pthread_mutex_unlock(&adev->lock);
10127 /* Assign compress record use case for second record */
10128 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10129 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10130 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10131 if (audio_extn_cin_applicable_stream(in)) {
10132 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010133 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010134 if (ret)
10135 goto err_open;
10136 }
10137 }
10138 }
kunleiz28c73e72019-03-27 17:24:04 +080010139 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010140 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010141
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010142 if (audio_extn_ssr_get_stream() != in)
10143 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010144
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010145 in->sample_rate = in->config.rate;
10146
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010147 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10148 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010149 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010150 in->sample_rate, in->bit_width,
10151 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010152 register_format(in->format, in->supported_formats);
10153 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10154 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010155
Dechen Chai22768452021-07-30 09:29:16 +053010156#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010157 in->error_log = error_log_create(
10158 ERROR_LOG_ENTRIES,
10159 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010160#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010161
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010162 /* This stream could be for sound trigger lab,
10163 get sound trigger pcm if present */
10164 audio_extn_sound_trigger_check_and_get_session(in);
10165
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010166 lock_input_stream(in);
10167 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10168 pthread_mutex_lock(&adev->lock);
10169 in->card_status = adev->card_status;
10170 pthread_mutex_unlock(&adev->lock);
10171 pthread_mutex_unlock(&in->lock);
10172
Aalique Grahame22e49102018-12-18 14:23:57 -080010173 stream_app_type_cfg_init(&in->app_type_cfg);
10174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010175 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010176
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010177 ret = io_streams_map_insert(adev, &in->stream.common,
10178 handle, AUDIO_PATCH_HANDLE_NONE);
10179 if (ret != 0)
10180 goto err_open;
10181
Susan Wang6dd13092021-01-25 10:27:11 -050010182 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010183
10184 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010185 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010186 pthread_mutex_unlock(&adev->lock);
10187
Eric Laurent994a6932013-07-17 11:51:42 -070010188 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010189 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010190
10191err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010192 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10193 free_record_usecase(adev, in->usecase);
10194 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010195 pthread_mutex_lock(&adev->lock);
10196 adev->pcm_record_uc_state = 0;
10197 pthread_mutex_unlock(&adev->lock);
10198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010199 free(in);
10200 *stream_in = NULL;
10201 return ret;
10202}
10203
10204static void adev_close_input_stream(struct audio_hw_device *dev,
10205 struct audio_stream_in *stream)
10206{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010207 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010208 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010209 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010210
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010211 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010212
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010213 if (in == NULL) {
10214 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10215 return;
10216 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010217 io_streams_map_remove(adev, in->capture_handle);
10218
Susan Wang6dd13092021-01-25 10:27:11 -050010219 // remove out_ctxt early to prevent the stream
10220 // being opened in a race condition
10221 pthread_mutex_lock(&adev->lock);
10222 list_remove(&in->in_ctxt.list);
10223 pthread_mutex_unlock(&adev->lock);
10224
kunleiz70e57612018-12-28 17:50:23 +080010225 /* must deregister from sndmonitor first to prevent races
10226 * between the callback and close_stream
10227 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010228 audio_extn_snd_mon_unregister_listener(stream);
10229
kunleiz70e57612018-12-28 17:50:23 +080010230 /* Disable echo reference if there are no active input, hfp call
10231 * and sound trigger while closing input stream
10232 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010233 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010234 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010235 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10236 struct listnode out_devices;
10237 list_init(&out_devices);
10238 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010239 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010240 } else
kunleiz70e57612018-12-28 17:50:23 +080010241 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010242
Dechen Chai22768452021-07-30 09:29:16 +053010243#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010244 error_log_destroy(in->error_log);
10245 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010246#endif
Pallavid7c7a272018-01-16 11:22:55 +053010247
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010248 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010249 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010250 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010251 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010252 if (ret != 0)
10253 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10254 __func__, ret);
10255 } else
10256 in_standby(&stream->common);
10257
Weiyin Jiang280ea742020-09-08 20:28:22 +080010258 pthread_mutex_destroy(&in->lock);
10259 pthread_mutex_destroy(&in->pre_lock);
10260
Revathi Uddarajud2634032017-12-07 14:42:34 +053010261 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010262 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10263 free_record_usecase(adev, in->usecase);
10264 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010265 adev->pcm_record_uc_state = 0;
10266 }
10267
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010268 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10269 adev->enable_voicerx = false;
10270 }
10271
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010272 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010273 audio_extn_ssr_deinit();
10274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010275
Garmond Leunge2433c32017-09-28 21:51:22 -070010276 if (audio_extn_ffv_get_stream() == in) {
10277 audio_extn_ffv_stream_deinit();
10278 }
10279
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010280 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -070010281 audio_extn_compr_cap_format_supported(in->config.format))
10282 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010283
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010284 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010285 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010286
Mingming Yinfd7607b2016-01-22 12:48:44 -080010287 if (in->is_st_session) {
10288 ALOGV("%s: sound trigger pcm stop lab", __func__);
10289 audio_extn_sound_trigger_stop_lab(in);
10290 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010291 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010292 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010293 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010294 return;
10295}
10296
Aalique Grahame22e49102018-12-18 14:23:57 -080010297/* verifies input and output devices and their capabilities.
10298 *
10299 * This verification is required when enabling extended bit-depth or
10300 * sampling rates, as not all qcom products support it.
10301 *
10302 * Suitable for calling only on initialization such as adev_open().
10303 * It fills the audio_device use_case_table[] array.
10304 *
10305 * Has a side-effect that it needs to configure audio routing / devices
10306 * in order to power up the devices and read the device parameters.
10307 * It does not acquire any hw device lock. Should restore the devices
10308 * back to "normal state" upon completion.
10309 */
10310static int adev_verify_devices(struct audio_device *adev)
10311{
10312 /* enumeration is a bit difficult because one really wants to pull
10313 * the use_case, device id, etc from the hidden pcm_device_table[].
10314 * In this case there are the following use cases and device ids.
10315 *
10316 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10317 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10318 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10319 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10320 * [USECASE_AUDIO_RECORD] = {0, 0},
10321 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10322 * [USECASE_VOICE_CALL] = {2, 2},
10323 *
10324 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10325 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10326 */
10327
10328 /* should be the usecases enabled in adev_open_input_stream() */
10329 static const int test_in_usecases[] = {
10330 USECASE_AUDIO_RECORD,
10331 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10332 };
10333 /* should be the usecases enabled in adev_open_output_stream()*/
10334 static const int test_out_usecases[] = {
10335 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10336 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10337 };
10338 static const usecase_type_t usecase_type_by_dir[] = {
10339 PCM_PLAYBACK,
10340 PCM_CAPTURE,
10341 };
10342 static const unsigned flags_by_dir[] = {
10343 PCM_OUT,
10344 PCM_IN,
10345 };
10346
10347 size_t i;
10348 unsigned dir;
10349 const unsigned card_id = adev->snd_card;
10350
10351 for (dir = 0; dir < 2; ++dir) {
10352 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10353 const unsigned flags_dir = flags_by_dir[dir];
10354 const size_t testsize =
10355 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10356 const int *testcases =
10357 dir ? test_in_usecases : test_out_usecases;
10358 const audio_devices_t audio_device =
10359 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10360
10361 for (i = 0; i < testsize; ++i) {
10362 const audio_usecase_t audio_usecase = testcases[i];
10363 int device_id;
10364 struct pcm_params **pparams;
10365 struct stream_out out;
10366 struct stream_in in;
10367 struct audio_usecase uc_info;
10368 int retval;
10369
10370 pparams = &adev->use_case_table[audio_usecase];
10371 pcm_params_free(*pparams); /* can accept null input */
10372 *pparams = NULL;
10373
10374 /* find the device ID for the use case (signed, for error) */
10375 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10376 if (device_id < 0)
10377 continue;
10378
10379 /* prepare structures for device probing */
10380 memset(&uc_info, 0, sizeof(uc_info));
10381 uc_info.id = audio_usecase;
10382 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010383 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010384 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010385 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010386 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010387 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010388 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10389 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010390 }
10391 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010392 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010393 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010394 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010395 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010396 uc_info.in_snd_device = SND_DEVICE_NONE;
10397 uc_info.out_snd_device = SND_DEVICE_NONE;
10398 list_add_tail(&adev->usecase_list, &uc_info.list);
10399
10400 /* select device - similar to start_(in/out)put_stream() */
10401 retval = select_devices(adev, audio_usecase);
10402 if (retval >= 0) {
10403 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10404#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010405 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010406 if (*pparams) {
10407 ALOGV("%s: (%s) card %d device %d", __func__,
10408 dir ? "input" : "output", card_id, device_id);
10409 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10410 } else {
10411 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10412 }
10413#endif
10414 }
10415
10416 /* deselect device - similar to stop_(in/out)put_stream() */
10417 /* 1. Get and set stream specific mixer controls */
10418 retval = disable_audio_route(adev, &uc_info);
10419 /* 2. Disable the rx device */
10420 retval = disable_snd_device(adev,
10421 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10422 list_remove(&uc_info.list);
10423 }
10424 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010425 return 0;
10426}
10427
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010428int update_patch(unsigned int num_sources,
10429 const struct audio_port_config *sources,
10430 unsigned int num_sinks,
10431 const struct audio_port_config *sinks,
10432 audio_patch_handle_t handle,
10433 struct audio_patch_info *p_info,
10434 patch_type_t patch_type, bool new_patch)
10435{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010436 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010437
10438 if (p_info == NULL) {
10439 ALOGE("%s: Invalid patch pointer", __func__);
10440 return -EINVAL;
10441 }
10442
10443 if (new_patch) {
10444 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10445 if (p_info->patch == NULL) {
10446 ALOGE("%s: Could not allocate patch", __func__);
10447 return -ENOMEM;
10448 }
10449 }
10450
10451 p_info->patch->id = handle;
10452 p_info->patch->num_sources = num_sources;
10453 p_info->patch->num_sinks = num_sinks;
10454
10455 for (int i = 0; i < num_sources; i++)
10456 p_info->patch->sources[i] = sources[i];
10457 for (int i = 0; i < num_sinks; i++)
10458 p_info->patch->sinks[i] = sinks[i];
10459
10460 p_info->patch_type = patch_type;
10461 return 0;
10462}
10463
10464audio_patch_handle_t generate_patch_handle()
10465{
10466 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10467 if (++patch_handle < 0)
10468 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10469 return patch_handle;
10470}
10471
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010472int adev_create_audio_patch(struct audio_hw_device *dev,
10473 unsigned int num_sources,
10474 const struct audio_port_config *sources,
10475 unsigned int num_sinks,
10476 const struct audio_port_config *sinks,
10477 audio_patch_handle_t *handle)
10478{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010479 int ret = 0;
10480 struct audio_device *adev = (struct audio_device *)dev;
10481 struct audio_patch_info *p_info = NULL;
10482 patch_type_t patch_type = PATCH_NONE;
10483 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10484 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10485 struct audio_stream_info *s_info = NULL;
10486 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010487 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010488 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10489 bool new_patch = false;
10490 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010491
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010492 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10493 num_sources, num_sinks, *handle);
10494
10495 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10496 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10497 ALOGE("%s: Invalid patch arguments", __func__);
10498 ret = -EINVAL;
10499 goto done;
10500 }
10501
10502 if (num_sources > 1) {
10503 ALOGE("%s: Multiple sources are not supported", __func__);
10504 ret = -EINVAL;
10505 goto done;
10506 }
10507
10508 if (sources == NULL || sinks == NULL) {
10509 ALOGE("%s: Invalid sources or sinks port config", __func__);
10510 ret = -EINVAL;
10511 goto done;
10512 }
10513
10514 ALOGV("%s: source role %d, source type %d", __func__,
10515 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010516 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010517
10518 // Populate source/sink information and fetch stream info
10519 switch (sources[0].type) {
10520 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10521 device_type = sources[0].ext.device.type;
10522 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010523 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010524 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10525 patch_type = PATCH_CAPTURE;
10526 io_handle = sinks[0].ext.mix.handle;
10527 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010528 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010529 __func__, device_type, io_handle);
10530 } else {
10531 // Device to device patch is not implemented.
10532 // This space will need changes if audio HAL
10533 // handles device to device patches in the future.
10534 patch_type = PATCH_DEVICE_LOOPBACK;
10535 }
10536 break;
10537 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10538 io_handle = sources[0].ext.mix.handle;
10539 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010540 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010541 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010542 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010543 }
10544 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010545 ALOGD("%s: Playback patch from mix handle %d to device %x",
10546 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010547 break;
10548 case AUDIO_PORT_TYPE_SESSION:
10549 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010550 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10551 ret = -EINVAL;
10552 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010553 }
10554
10555 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010556
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010557 // Generate patch info and update patch
10558 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010559 *handle = generate_patch_handle();
10560 p_info = (struct audio_patch_info *)
10561 calloc(1, sizeof(struct audio_patch_info));
10562 if (p_info == NULL) {
10563 ALOGE("%s: Failed to allocate memory", __func__);
10564 pthread_mutex_unlock(&adev->lock);
10565 ret = -ENOMEM;
10566 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010567 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010568 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010569 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010570 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010571 if (p_info == NULL) {
10572 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10573 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010574 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010575 ret = -EINVAL;
10576 goto done;
10577 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010578 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010579 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010580 *handle, p_info, patch_type, new_patch);
10581
10582 // Fetch stream info of associated mix for playback or capture patches
10583 if (p_info->patch_type == PATCH_PLAYBACK ||
10584 p_info->patch_type == PATCH_CAPTURE) {
10585 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10586 if (s_info == NULL) {
10587 ALOGE("%s: Failed to obtain stream info", __func__);
10588 if (new_patch)
10589 free(p_info);
10590 pthread_mutex_unlock(&adev->lock);
10591 ret = -EINVAL;
10592 goto done;
10593 }
10594 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10595 s_info->patch_handle = *handle;
10596 stream = s_info->stream;
10597 }
10598 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010599
10600 // Update routing for stream
10601 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010602 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010603 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010604 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010605 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010606 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010607 if (ret < 0) {
10608 pthread_mutex_lock(&adev->lock);
10609 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10610 if (new_patch)
10611 free(p_info);
10612 pthread_mutex_unlock(&adev->lock);
10613 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10614 goto done;
10615 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010616 }
10617
10618 // Add new patch to patch map
10619 if (!ret && new_patch) {
10620 pthread_mutex_lock(&adev->lock);
10621 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010622 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010623 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010624 }
10625
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010626done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010627 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010628 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010629 num_sources,
10630 sources,
10631 num_sinks,
10632 sinks,
10633 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010634 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010635 num_sources,
10636 sources,
10637 num_sinks,
10638 sinks,
10639 handle);
10640 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010641}
10642
10643int adev_release_audio_patch(struct audio_hw_device *dev,
10644 audio_patch_handle_t handle)
10645{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010646 struct audio_device *adev = (struct audio_device *) dev;
10647 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010648 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010649 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010650
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010651 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10652 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10653 ret = -EINVAL;
10654 goto done;
10655 }
10656
10657 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010658 pthread_mutex_lock(&adev->lock);
10659 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010660 if (p_info == NULL) {
10661 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010662 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010663 ret = -EINVAL;
10664 goto done;
10665 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010666 struct audio_patch *patch = p_info->patch;
10667 if (patch == NULL) {
10668 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010669 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010670 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010671 goto done;
10672 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010673 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10674 switch (patch->sources[0].type) {
10675 case AUDIO_PORT_TYPE_MIX:
10676 io_handle = patch->sources[0].ext.mix.handle;
10677 break;
10678 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010679 if (p_info->patch_type == PATCH_CAPTURE)
10680 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010681 break;
10682 case AUDIO_PORT_TYPE_SESSION:
10683 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010684 pthread_mutex_unlock(&adev->lock);
10685 ret = -EINVAL;
10686 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010687 }
10688
10689 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010690 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010691 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010692 if (patch_type == PATCH_PLAYBACK ||
10693 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010694 struct audio_stream_info *s_info =
10695 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10696 if (s_info == NULL) {
10697 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10698 pthread_mutex_unlock(&adev->lock);
10699 goto done;
10700 }
10701 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10702 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010703 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010704 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010705
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010706 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010707 struct listnode devices;
10708 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010709 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010710 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010711 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010712 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010713 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010714 }
10715
10716 if (ret < 0)
10717 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10718
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010719done:
10720 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10721 audio_extn_auto_hal_release_audio_patch(dev, handle);
10722
10723 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010724 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010725}
10726
10727int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10728{
Derek Chenf13dd492018-11-13 14:53:51 -080010729 int ret = 0;
10730
10731 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10732 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10733 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010734}
10735
10736int adev_set_audio_port_config(struct audio_hw_device *dev,
10737 const struct audio_port_config *config)
10738{
Derek Chenf13dd492018-11-13 14:53:51 -080010739 int ret = 0;
10740
10741 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10742 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10743 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010744}
10745
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010746static int adev_dump(const audio_hw_device_t *device __unused,
10747 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010748{
10749 return 0;
10750}
10751
10752static int adev_close(hw_device_t *device)
10753{
Aalique Grahame22e49102018-12-18 14:23:57 -080010754 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010755 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010756
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010757 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010758 return 0;
10759
10760 pthread_mutex_lock(&adev_init_lock);
10761
10762 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010763 if (audio_extn_spkr_prot_is_enabled())
10764 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010765 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010766 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010767 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010768 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010769 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010770 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010771 audio_extn_utils_release_streams_cfg_lists(
10772 &adev->streams_output_cfg_list,
10773 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010774 if (audio_extn_qap_is_enabled())
10775 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010776 if (audio_extn_qaf_is_enabled())
10777 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010778 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010779 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010780 free(adev->snd_dev_ref_cnt);
10781 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010782 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10783 pcm_params_free(adev->use_case_table[i]);
10784 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010785 if (adev->adm_deinit)
10786 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010787 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010788 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010789 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010790 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010791 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010792 if (adev->device_cfg_params) {
10793 free(adev->device_cfg_params);
10794 adev->device_cfg_params = NULL;
10795 }
Derek Chend2530072014-11-24 12:39:14 -080010796 if(adev->ext_hw_plugin)
10797 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010798 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010799 free_map(adev->patch_map);
10800 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010801 free(device);
10802 adev = NULL;
10803 }
10804 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010805 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010806 return 0;
10807}
10808
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010809/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10810 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10811 * just that it _might_ work.
10812 */
10813static int period_size_is_plausible_for_low_latency(int period_size)
10814{
10815 switch (period_size) {
10816 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010817 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010818 case 240:
10819 case 320:
10820 case 480:
10821 return 1;
10822 default:
10823 return 0;
10824 }
10825}
10826
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010827static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10828{
10829 bool is_snd_card_status = false;
10830 bool is_ext_device_status = false;
10831 char value[32];
10832 int card = -1;
10833 card_status_t status;
10834
10835 if (cookie != adev || !parms)
10836 return;
10837
10838 if (!parse_snd_card_status(parms, &card, &status)) {
10839 is_snd_card_status = true;
10840 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10841 is_ext_device_status = true;
10842 } else {
10843 // not a valid event
10844 return;
10845 }
10846
10847 pthread_mutex_lock(&adev->lock);
10848 if (card == adev->snd_card || is_ext_device_status) {
10849 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010850 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010851 adev->card_status = status;
10852 platform_snd_card_update(adev->platform, status);
10853 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010854 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010855 if (status == CARD_STATUS_OFFLINE)
10856 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010857 } else if (is_ext_device_status) {
10858 platform_set_parameters(adev->platform, parms);
10859 }
10860 }
10861 pthread_mutex_unlock(&adev->lock);
10862 return;
10863}
10864
Weiyin Jiang280ea742020-09-08 20:28:22 +080010865/* adev lock held */
10866int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010867{
10868 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010869 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010870 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010871 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010872
10873 uc_info = get_usecase_from_list(adev, out->usecase);
10874 if (uc_info == NULL) {
10875 ALOGE("%s: Could not find the usecase (%d) in the list",
10876 __func__, out->usecase);
10877 return -EINVAL;
10878 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010879 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010880
Zhou Songbaddf9f2020-11-20 13:57:39 +080010881 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10882 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010883
10884 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010885 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010886 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010887 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010888 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010889 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10890 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010891
10892 if (is_offload_usecase(out->usecase)) {
10893 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010894 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010895 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10896 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10897 } else {
10898 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010899 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010900 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010901 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010902 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010903 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010904 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010905 // mute stream and switch to speaker if suspended
10906 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010907 assign_devices(&devices, &out->device_list);
10908 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010909 list_for_each(node, &adev->usecase_list) {
10910 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010911 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10912 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010913 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010914 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10915 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010916 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10917 break;
10918 }
10919 }
Zhou Songcf77af02021-05-14 18:21:14 +080010920 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10921 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010922 out->a2dp_muted = true;
10923 if (is_offload_usecase(out->usecase)) {
10924 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10925 compress_pause(out->compr);
10926 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010927 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010928 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10929 out_set_voip_volume(&out->stream, (float)0, (float)0);
10930 else
10931 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10932
Zhou Song8edbbdb2021-01-14 16:48:03 +080010933 /* wait for stale pcm drained before switching to speaker */
10934 uint32_t latency =
10935 (out->config.period_count * out->config.period_size * 1000) /
10936 (out->config.rate);
10937 usleep(latency * 1000);
10938 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010939 }
10940 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010941 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10942 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010943 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010944 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10945 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010946 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010947 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010948 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010949 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010950 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010951 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010952 ALOGV("%s: exit", __func__);
10953 return 0;
10954}
10955
Haynes Mathew George01156f92018-04-13 15:29:54 -070010956void adev_on_battery_status_changed(bool charging)
10957{
10958 pthread_mutex_lock(&adev->lock);
10959 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10960 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010961 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010962 pthread_mutex_unlock(&adev->lock);
10963}
10964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010965static int adev_open(const hw_module_t *module, const char *name,
10966 hw_device_t **device)
10967{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010968 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010969 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010970 char mixer_ctl_name[128] = {0};
10971 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010972
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010973 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010974 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10975
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010976 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010977 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010978 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010979 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010980 ALOGD("%s: returning existing instance of adev", __func__);
10981 ALOGD("%s: exit", __func__);
10982 pthread_mutex_unlock(&adev_init_lock);
10983 return 0;
10984 }
10985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010986 adev = calloc(1, sizeof(struct audio_device));
10987
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010988 if (!adev) {
10989 pthread_mutex_unlock(&adev_init_lock);
10990 return -ENOMEM;
10991 }
10992
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010993 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10994
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010995 // register audio ext hidl at the earliest
10996 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010997#ifdef DYNAMIC_LOG_ENABLED
10998 register_for_dynamic_logging("hal");
10999#endif
11000
Derek Chenf939fb72018-11-13 13:34:41 -080011001 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011002 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011003 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11004 maj_version = atoi(value);
11005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011006 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011007 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011008 adev->device.common.module = (struct hw_module_t *)module;
11009 adev->device.common.close = adev_close;
11010
11011 adev->device.init_check = adev_init_check;
11012 adev->device.set_voice_volume = adev_set_voice_volume;
11013 adev->device.set_master_volume = adev_set_master_volume;
11014 adev->device.get_master_volume = adev_get_master_volume;
11015 adev->device.set_master_mute = adev_set_master_mute;
11016 adev->device.get_master_mute = adev_get_master_mute;
11017 adev->device.set_mode = adev_set_mode;
11018 adev->device.set_mic_mute = adev_set_mic_mute;
11019 adev->device.get_mic_mute = adev_get_mic_mute;
11020 adev->device.set_parameters = adev_set_parameters;
11021 adev->device.get_parameters = adev_get_parameters;
11022 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11023 adev->device.open_output_stream = adev_open_output_stream;
11024 adev->device.close_output_stream = adev_close_output_stream;
11025 adev->device.open_input_stream = adev_open_input_stream;
11026 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011027 adev->device.create_audio_patch = adev_create_audio_patch;
11028 adev->device.release_audio_patch = adev_release_audio_patch;
11029 adev->device.get_audio_port = adev_get_audio_port;
11030 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011031 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011032 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011033
11034 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011035 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011036 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011037 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011038 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011039 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011040 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011041 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011042 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011043 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011044 /* Init audio and voice feature */
11045 audio_extn_feature_init();
11046 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011047 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011048 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011049 list_init(&adev->active_inputs_list);
11050 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011051 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011052 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11053 audio_extn_utils_hash_eq);
11054 if (!adev->io_streams_map) {
11055 ALOGE("%s: Could not create io streams map", __func__);
11056 ret = -ENOMEM;
11057 goto adev_open_err;
11058 }
11059 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11060 audio_extn_utils_hash_eq);
11061 if (!adev->patch_map) {
11062 ALOGE("%s: Could not create audio patch map", __func__);
11063 ret = -ENOMEM;
11064 goto adev_open_err;
11065 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011066 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011067 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011068 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011069 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011070 adev->perf_lock_opts[0] = 0x101;
11071 adev->perf_lock_opts[1] = 0x20E;
11072 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011073 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011074 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011075 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011076 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011077 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011078 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011079
Zhou Song68ebc352019-12-05 17:11:15 +080011080 audio_extn_perf_lock_init();
11081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011082 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011083 adev->platform = platform_init(adev);
11084 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011085 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011086 ret = -EINVAL;
11087 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011088 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011089
Aalique Grahame22e49102018-12-18 14:23:57 -080011090 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011091 if (audio_extn_qap_is_enabled()) {
11092 ret = audio_extn_qap_init(adev);
11093 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011094 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011095 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011096 }
11097 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11098 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11099 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011100
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011101 if (audio_extn_qaf_is_enabled()) {
11102 ret = audio_extn_qaf_init(adev);
11103 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011104 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011105 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011106 }
11107
11108 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11109 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11110 }
11111
Derek Chenae7b0342019-02-08 15:17:04 -080011112 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011113 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11114
Eric Laurentc4aef752013-09-12 17:45:53 -070011115 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11116 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11117 if (adev->visualizer_lib == NULL) {
11118 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11119 } else {
11120 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11121 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011122 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011123 "visualizer_hal_start_output");
11124 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011125 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011126 "visualizer_hal_stop_output");
11127 }
11128 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011129 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011130 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011131 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011132 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011133 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011134 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011135
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011136 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11137 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11138 if (adev->offload_effects_lib == NULL) {
11139 ALOGE("%s: DLOPEN failed for %s", __func__,
11140 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11141 } else {
11142 ALOGV("%s: DLOPEN successful for %s", __func__,
11143 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11144 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011145 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011146 "offload_effects_bundle_hal_start_output");
11147 adev->offload_effects_stop_output =
11148 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11149 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011150 adev->offload_effects_set_hpx_state =
11151 (int (*)(bool))dlsym(adev->offload_effects_lib,
11152 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011153 adev->offload_effects_get_parameters =
11154 (void (*)(struct str_parms *, struct str_parms *))
11155 dlsym(adev->offload_effects_lib,
11156 "offload_effects_bundle_get_parameters");
11157 adev->offload_effects_set_parameters =
11158 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11159 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011160 }
11161 }
11162
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011163 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11164 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11165 if (adev->adm_lib == NULL) {
11166 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11167 } else {
11168 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11169 adev->adm_init = (adm_init_t)
11170 dlsym(adev->adm_lib, "adm_init");
11171 adev->adm_deinit = (adm_deinit_t)
11172 dlsym(adev->adm_lib, "adm_deinit");
11173 adev->adm_register_input_stream = (adm_register_input_stream_t)
11174 dlsym(adev->adm_lib, "adm_register_input_stream");
11175 adev->adm_register_output_stream = (adm_register_output_stream_t)
11176 dlsym(adev->adm_lib, "adm_register_output_stream");
11177 adev->adm_deregister_stream = (adm_deregister_stream_t)
11178 dlsym(adev->adm_lib, "adm_deregister_stream");
11179 adev->adm_request_focus = (adm_request_focus_t)
11180 dlsym(adev->adm_lib, "adm_request_focus");
11181 adev->adm_abandon_focus = (adm_abandon_focus_t)
11182 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011183 adev->adm_set_config = (adm_set_config_t)
11184 dlsym(adev->adm_lib, "adm_set_config");
11185 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11186 dlsym(adev->adm_lib, "adm_request_focus_v2");
11187 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11188 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11189 adev->adm_on_routing_change = (adm_on_routing_change_t)
11190 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011191 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11192 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011193 }
11194 }
11195
Aalique Grahame22e49102018-12-18 14:23:57 -080011196 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011197 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011198 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011199 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011200 //initialize this to false for now,
11201 //this will be set to true through set param
11202 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011203
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011204 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011205 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011206
11207 if (k_enable_extended_precision)
11208 adev_verify_devices(adev);
11209
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011210 adev->dsp_bit_width_enforce_mode =
11211 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011212
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011213 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11214 &adev->streams_output_cfg_list,
11215 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011216
Kiran Kandi910e1862013-10-29 13:29:42 -070011217 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011218
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011219 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011220 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011221 trial = atoi(value);
11222 if (period_size_is_plausible_for_low_latency(trial)) {
11223 pcm_config_low_latency.period_size = trial;
11224 pcm_config_low_latency.start_threshold = trial / 4;
11225 pcm_config_low_latency.avail_min = trial / 4;
11226 configured_low_latency_capture_period_size = trial;
11227 }
11228 }
ronghuiz93177262021-04-21 19:58:13 +080011229 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011230 trial = atoi(value);
11231 if (period_size_is_plausible_for_low_latency(trial)) {
11232 configured_low_latency_capture_period_size = trial;
11233 }
11234 }
11235
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011236 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11237
Eric Laurent4b084132018-10-19 17:33:43 -070011238 adev->camera_orientation = CAMERA_DEFAULT;
11239
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011240 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011241 af_period_multiplier = atoi(value);
11242 if (af_period_multiplier < 0)
11243 af_period_multiplier = 2;
11244 else if (af_period_multiplier > 4)
11245 af_period_multiplier = 4;
11246
11247 ALOGV("new period_multiplier = %d", af_period_multiplier);
11248 }
11249
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011250 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011251
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011252 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011253 pthread_mutex_unlock(&adev_init_lock);
11254
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011255 if (adev->adm_init)
11256 adev->adm_data = adev->adm_init();
11257
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011258 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011259 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011260
11261 audio_extn_snd_mon_init();
11262 pthread_mutex_lock(&adev->lock);
11263 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11264 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011265 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11266 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011267 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11268 /*
11269 * if the battery state callback happens before charging can be queried,
11270 * it will be guarded with the adev->lock held in the cb function and so
11271 * the callback value will reflect the latest state
11272 */
11273 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011274 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011275 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011276 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011277 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011278 /* Allocate memory for Device config params */
11279 adev->device_cfg_params = (struct audio_device_config_param*)
11280 calloc(platform_get_max_codec_backend(),
11281 sizeof(struct audio_device_config_param));
11282 if (adev->device_cfg_params == NULL)
11283 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011284
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011285 /*
11286 * Check if new PSPD matrix mixer control is supported. If not
11287 * supported, then set flag so that old mixer ctrl is sent while
11288 * sending pspd coefficients on older kernel version. Query mixer
11289 * control for default pcm id and channel value one.
11290 */
11291 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11292 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11293
11294 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11295 if (!ctl) {
11296 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11297 __func__, mixer_ctl_name);
11298 adev->use_old_pspd_mix_ctrl = true;
11299 }
11300
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011301 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011302 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011303
11304adev_open_err:
11305 free_map(adev->patch_map);
11306 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011307 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011308 pthread_mutex_destroy(&adev->lock);
11309 free(adev);
11310 adev = NULL;
11311 *device = NULL;
11312 pthread_mutex_unlock(&adev_init_lock);
11313 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011314}
11315
11316static struct hw_module_methods_t hal_module_methods = {
11317 .open = adev_open,
11318};
11319
11320struct audio_module HAL_MODULE_INFO_SYM = {
11321 .common = {
11322 .tag = HARDWARE_MODULE_TAG,
11323 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11324 .hal_api_version = HARDWARE_HAL_API_VERSION,
11325 .id = AUDIO_HARDWARE_MODULE_ID,
11326 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011327 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011328 .methods = &hal_module_methods,
11329 },
11330};